From capacitor-quality
Guides debugging Capacitor apps on iOS/Android: WebView inspection via Safari/Chrome DevTools, native debugging in Xcode/Android Studio, crash logs, network analysis, and common issues.
npx claudepluginhub cap-go/capgo-skills --plugin capacitor-qualityThis skill uses the workspace's default tool permissions.
Complete guide to debugging Capacitor apps on iOS and Android.
Debugs mobile app crashes, performance issues, platform-specific bugs, device constraints, and connectivity problems on iOS and Android using Xcode, logs, and memory inspection.
Debugs iOS, Android, and React Native mobile apps for crashes, memory leaks, performance issues, network problems using Xcode Instruments, Android Profiler, LLDB, Logcat.
Guides accessing, filtering, and streaming iOS/Android device logs for Capacitor apps using devicectl, adb logcat, Console.app, and simctl. For debugging crashes and app issues.
Share bugs, ideas, or general feedback.
Complete guide to debugging Capacitor apps on iOS and Android.
| Platform | WebView Debug | Native Debug | Logs |
|---|---|---|---|
| iOS | Safari Web Inspector | Xcode Debugger | Console.app |
| Android | Chrome DevTools | Android Studio | adb logcat |
Enable on device:
Enable in Xcode (capacitor.config.ts):
const config: CapacitorConfig = {
ios: {
webContentsDebuggingEnabled: true, // Required for iOS 16.4+
},
};
Connect Safari:
Debug:
const config: CapacitorConfig = {
android: {
webContentsDebuggingEnabled: true,
},
};
Connect Chrome:
chrome://inspectDebug features:
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"
}
]
}
npx cap open ios
Set breakpoints:
breakpoint set --name methodName in LLDBRun with debugger:
LLDB Console commands:
# Print variable
po myVariable
# Print object description
p myObject
# Continue execution
continue
# Step over
next
# Step into
step
# Print backtrace
bt
npx cap open android
Attach debugger:
Set breakpoints:
Debug console:
# Evaluate expression
myVariable
# Run method
myObject.toString()
package:com.yourapp// 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');
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)
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)
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:
Solution checklist:
npx cap synccd ios/App && pod installError: 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:
npm install @capgo/plugin-namenpx cap syncDiagnosis:
// 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:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
server: {
cleartext: true, // Only for development!
}
import { CapacitorHttp } from '@capacitor/core';
const response = await CapacitorHttp.request({
method: 'GET',
url: 'https://api.example.com/data',
});
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" />
Diagnosis:
dist/ folder existswebDir in capacitor.config.tsSolutions:
# Rebuild web assets
npm run build
# Sync to native
npx cap sync
# Check config
cat capacitor.config.ts
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.
// 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);
Use Chrome DevTools Memory tab:
# Run with Leaks instrument
xcrun instruments -t Leaks -D output.trace YourApp.app
Add to build.gradle:
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12'
When debugging issues:
rm -rf node_modules && npm install)