debugging-capacitor
Debugging Capacitor Applications
Complete guide to debugging Capacitor apps on iOS and Android.
When to Use This Skill
- User reports app crashes
- User needs to debug WebView/JavaScript
- User needs to debug native code
- User has network/API issues
- User sees unexpected behavior
- User asks how to debug
Quick Reference: Debugging Tools
| Platform | WebView Debug | Native Debug | Logs |
|---|---|---|---|
| iOS | Safari Web Inspector | Xcode Debugger | Console.app |
| Android | Chrome DevTools | Android Studio | adb logcat |
WebView Debugging
iOS: Safari Web Inspector
-
Enable on device:
- Settings > Safari > Advanced > Web Inspector: ON
- Settings > Safari > Advanced > JavaScript: ON
-
Enable in Xcode (capacitor.config.ts):
const config: CapacitorConfig = {
ios: {
webContentsDebuggingEnabled: true, // Required for iOS 16.4+
},
};
-
Connect Safari:
- Open Safari on Mac
- Develop menu > [Device Name] > [App Name]
- If no Develop menu: Safari > Settings > Advanced > Show Develop menu
-
Debug:
- Console: View JavaScript logs
- Network: Inspect API calls
- Elements: Inspect DOM
- Sources: Set breakpoints
Android: Chrome DevTools
- Enable in config (capacitor.config.ts):
const config: CapacitorConfig = {
android: {
webContentsDebuggingEnabled: true,
},
};
-
Connect Chrome:
- Open Chrome on computer
- Navigate to
chrome://inspect - Your device/emulator should appear
- Click "inspect" under your app
-
Debug features:
- Console: JavaScript logs
- Network: API requests
- Performance: Profiling
- Application: Storage, cookies
Remote Debugging with VS Code
Install "Debugger for Chrome" extension:
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "attach",
"name": "Attach to Android WebView",
"port": 9222,
"webRoot": "${workspaceFolder}/dist"
}
]
}
Native Debugging
iOS: Xcode Debugger
- Open in Xcode:
bunx cap open ios
-
Set breakpoints:
- Click line number in Swift/Obj-C files
- Or use
breakpoint set --name methodNamein LLDB
-
Run with debugger:
- Product > Run (Cmd + R)
- Or click Play button
-
LLDB Console commands:
# Print variable
po myVariable
# Print object description
p myObject
# Continue execution
continue
# Step over
next
# Step into
step
# Print backtrace
bt
- View crash logs:
- Window > Devices and Simulators
- Select device > View Device Logs
Android: Android Studio Debugger
- Open in Android Studio:
bunx cap open android
-
Attach debugger:
- Run > Attach Debugger to Android Process
- Select your app
-
Set breakpoints:
- Click line number in Java/Kotlin files
-
Debug console:
# Evaluate expression
myVariable
# Run method
myObject.toString()
- Logcat shortcuts:
- View > Tool Windows > Logcat
- Filter by package:
package:com.yourapp
Console Logging
JavaScript Side
// Basic logging
console.log('Debug info:', data);
console.warn('Warning:', issue);
console.error('Error:', error);
// Grouped logs
console.group('API Call');
console.log('URL:', url);
console.log('Response:', response);
console.groupEnd();
// Table format
console.table(arrayOfObjects);
// Timing
console.time('operation');
// ... operation
console.timeEnd('operation');
Native Side (iOS)
import os.log
let logger = Logger(subsystem: "com.yourapp", category: "MyPlugin")
// Log levels
logger.debug("Debug message")
logger.info("Info message")
logger.warning("Warning message")
logger.error("Error message")
// With data
logger.info("User ID: \(userId)")
// Legacy NSLog (shows in Console.app)
NSLog("Legacy log: %@", message)
Native Side (Android)
import android.util.Log
// Log levels
Log.v("MyPlugin", "Verbose message")
Log.d("MyPlugin", "Debug message")
Log.i("MyPlugin", "Info message")
Log.w("MyPlugin", "Warning message")
Log.e("MyPlugin", "Error message")
// With exception
Log.e("MyPlugin", "Error occurred", exception)
Common Issues and Solutions
Issue: App Crashes on Startup
Diagnosis:
# iOS - Check crash logs
xcrun simctl spawn booted log stream --level debug | grep -i crash
# Android - Check logcat
adb logcat *:E | grep -i "fatal\|crash"
Common causes:
- Missing plugin registration
- Invalid capacitor.config
- Missing native dependencies
Solution checklist:
- Run
bunx cap sync - iOS:
cd ios/App && pod install - Check Info.plist permissions
- Check AndroidManifest.xml permissions
Issue: Plugin Method Not Found
Error: Error: "MyPlugin" plugin is not implemented on ios/android
Diagnosis:
import { Capacitor } from '@capacitor/core';
// Check if plugin exists
console.log('Plugins:', Capacitor.Plugins);
console.log('MyPlugin available:', !!Capacitor.Plugins.MyPlugin);
Solutions:
- Ensure plugin is installed:
bun add @capgo/plugin-name - Run sync:
bunx cap sync - Check plugin is registered (native code)
Issue: Network Requests Failing
Diagnosis:
// Add request interceptor
const originalFetch = window.fetch;
window.fetch = async (...args) => {
console.log('Fetch:', args[0]);
try {
const response = await originalFetch(...args);
console.log('Response status:', response.status);
return response;
} catch (error) {
console.error('Fetch error:', error);
throw error;
}
};
Common causes:
- iOS ATS blocking HTTP: Add to Info.plist:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
- Android cleartext blocked: Add to capacitor.config.ts:
server: {
cleartext: true, // Only for development!
}
- CORS issues: Use native HTTP:
import { CapacitorHttp } from '@capacitor/core';
const response = await CapacitorHttp.request({
method: 'GET',
url: 'https://api.example.com/data',
});
Issue: Permission Denied
Diagnosis:
import { Permissions } from '@capacitor/core';
// Check permission status
const status = await Permissions.query({ name: 'camera' });
console.log('Camera permission:', status.state);
iOS: Check Info.plist has usage descriptions:
<key>NSCameraUsageDescription</key>
<string>We need camera access to scan documents</string>
Android: Check AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
Issue: White Screen on Launch
Diagnosis:
- Check WebView console for errors (Safari/Chrome)
- Check if
dist/folder exists - Verify
webDirin capacitor.config.ts
Solutions:
# Rebuild web assets
bun run build
# Sync to native
bunx cap sync
# Check config
cat capacitor.config.ts
Issue: Deep Links Not Working
Diagnosis:
import { App } from '@capacitor/app';
App.addListener('appUrlOpen', (event) => {
console.log('Deep link:', event.url);
});
iOS: Check Associated Domains entitlement and apple-app-site-association file.
Android: Check intent filters in AndroidManifest.xml.
Performance Debugging
JavaScript Performance
// Mark performance
performance.mark('start');
// ... operation
performance.mark('end');
performance.measure('operation', 'start', 'end');
const measures = performance.getEntriesByName('operation');
console.log('Duration:', measures[0].duration);
iOS Performance (Instruments)
- Product > Profile (Cmd + I)
- Choose template:
- Time Profiler: CPU usage
- Allocations: Memory usage
- Network: Network activity
Android Performance (Profiler)
- View > Tool Windows > Profiler
- Select:
- CPU: Method tracing
- Memory: Heap analysis
- Network: Request timeline
Memory Debugging
JavaScript Memory Leaks
Use Chrome DevTools Memory tab:
- Take heap snapshot
- Perform action
- Take another snapshot
- Compare snapshots
iOS Memory (Instruments)
# Run with Leaks instrument
xcrun instruments -t Leaks -D output.trace YourApp.app
Android Memory (LeakCanary)
Add to build.gradle:
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12'
Debugging Checklist
When debugging issues:
- Check WebView console (Safari/Chrome DevTools)
- Check native logs (Xcode Console/Logcat)
- Verify plugin is installed and synced
- Check permissions (Info.plist/AndroidManifest)
- Test on real device (not just simulator)
- Try clean build (
rm -rf node_modules && bun install) - Verify capacitor.config.ts settings
- Check for version mismatches (capacitor packages)
Resources
- Capacitor Debugging Guide: https://capacitorjs.com/docs/guides/debugging
- Safari Web Inspector: https://webkit.org/web-inspector
- Chrome DevTools: https://developer.chrome.com/docs/devtools
- Xcode Debugging: https://developer.apple.com/documentation/xcode/debugging
- Android Studio Debugging: https://developer.android.com/studio/debug