NYC
skills/cap-go/capacitor-skills/debugging-capacitor

debugging-capacitor

SKILL.md

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

  1. Enable on device:

    • Settings > Safari > Advanced > Web Inspector: ON
    • Settings > Safari > Advanced > JavaScript: ON
  2. Enable in Xcode (capacitor.config.ts):

const config: CapacitorConfig = {
  ios: {
    webContentsDebuggingEnabled: true, // Required for iOS 16.4+
  },
};
  1. Connect Safari:

    • Open Safari on Mac
    • Develop menu > [Device Name] > [App Name]
    • If no Develop menu: Safari > Settings > Advanced > Show Develop menu
  2. Debug:

    • Console: View JavaScript logs
    • Network: Inspect API calls
    • Elements: Inspect DOM
    • Sources: Set breakpoints

Android: Chrome DevTools

  1. Enable in config (capacitor.config.ts):
const config: CapacitorConfig = {
  android: {
    webContentsDebuggingEnabled: true,
  },
};
  1. Connect Chrome:

    • Open Chrome on computer
    • Navigate to chrome://inspect
    • Your device/emulator should appear
    • Click "inspect" under your app
  2. 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

  1. Open in Xcode:
bunx cap open ios
  1. Set breakpoints:

    • Click line number in Swift/Obj-C files
    • Or use breakpoint set --name methodName in LLDB
  2. Run with debugger:

    • Product > Run (Cmd + R)
    • Or click Play button
  3. LLDB Console commands:

# Print variable
po myVariable

# Print object description
p myObject

# Continue execution
continue

# Step over
next

# Step into
step

# Print backtrace
bt
  1. View crash logs:
    • Window > Devices and Simulators
    • Select device > View Device Logs

Android: Android Studio Debugger

  1. Open in Android Studio:
bunx cap open android
  1. Attach debugger:

    • Run > Attach Debugger to Android Process
    • Select your app
  2. Set breakpoints:

    • Click line number in Java/Kotlin files
  3. Debug console:

# Evaluate expression
myVariable

# Run method
myObject.toString()
  1. 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:

  1. Missing plugin registration
  2. Invalid capacitor.config
  3. 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:

  1. Ensure plugin is installed: bun add @capgo/plugin-name
  2. Run sync: bunx cap sync
  3. 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:

  1. iOS ATS blocking HTTP: Add to Info.plist:
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
  1. Android cleartext blocked: Add to capacitor.config.ts:
server: {
  cleartext: true, // Only for development!
}
  1. 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:

  1. Check WebView console for errors (Safari/Chrome)
  2. Check if dist/ folder exists
  3. Verify webDir in 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)

  1. Product > Profile (Cmd + I)
  2. Choose template:
    • Time Profiler: CPU usage
    • Allocations: Memory usage
    • Network: Network activity

Android Performance (Profiler)

  1. View > Tool Windows > Profiler
  2. Select:
    • CPU: Method tracing
    • Memory: Heap analysis
    • Network: Request timeline

Memory Debugging

JavaScript Memory Leaks

Use Chrome DevTools Memory tab:

  1. Take heap snapshot
  2. Perform action
  3. Take another snapshot
  4. 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

Weekly Installs
43
First Seen
Jan 25, 2026
Installed on
claude-code32
opencode22
github-copilot20
codex20
gemini-cli19
cursor19