> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/expo/expo/llms.txt
> Use this file to discover all available pages before exploring further.

# Debugging Development Builds

> Debug your Expo app with Chrome DevTools, React DevTools, and native debugging tools.

Development builds come with powerful debugging capabilities. This guide covers all available debugging tools and workflows.

## Available Debugging Tools

Expo provides multiple debugging methods:

<table>
  <thead>
    <tr>
      <th>Tool</th>
      <th>Purpose</th>
      <th>Platform</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>Chrome DevTools</td>
      <td>JavaScript debugging, console, network</td>
      <td>All</td>
    </tr>

    <tr>
      <td>React DevTools</td>
      <td>Component hierarchy, props, state</td>
      <td>All</td>
    </tr>

    <tr>
      <td>Expo DevTools</td>
      <td>Dev menu, inspector, plugins</td>
      <td>All</td>
    </tr>

    <tr>
      <td>Xcode Debugger</td>
      <td>Native iOS code</td>
      <td>iOS</td>
    </tr>

    <tr>
      <td>Android Studio</td>
      <td>Native Android code</td>
      <td>Android</td>
    </tr>

    <tr>
      <td>Network Inspector</td>
      <td>HTTP requests/responses</td>
      <td>All</td>
    </tr>
  </tbody>
</table>

## JavaScript Debugging

### Chrome DevTools

The primary tool for debugging JavaScript code.

<Steps>
  <Step title="Enable debugging">
    ```bash theme={null}
    # Start with debugging enabled
    npx expo start --dev-client
    ```

    In your development build:

    1. Shake device or press `Cmd+D` (iOS) / `Cmd+M` (Android)
    2. Select "Debug with Chrome"
  </Step>

  <Step title="Open DevTools">
    Chrome opens automatically at:

    ```
    http://localhost:8081/debugger-ui/
    ```

    Or manually open Chrome and press `Cmd+Option+J` (Mac) / `Ctrl+Shift+J` (Windows/Linux).
  </Step>

  <Step title="Set breakpoints">
    ```typescript title="app/index.tsx" theme={null}
    export default function HomeScreen() {
      const [count, setCount] = useState(0);
      
      const handlePress = () => {
        debugger; // Execution pauses here
        setCount(count + 1);
        console.log('Count:', count);
      };
      
      return (
        <Button onPress={handlePress} title="Increment" />
      );
    }
    ```
  </Step>
</Steps>

#### Console API

Use console methods for debugging:

```typescript theme={null}
// Basic logging
console.log('Simple message');
console.log('Multiple', 'arguments', { data: 'object' });

// Styled output
console.warn('Warning message');
console.error('Error message');
console.info('Info message');

// Grouped output
console.group('User Data');
console.log('Name:', user.name);
console.log('Email:', user.email);
console.groupEnd();

// Timing
console.time('fetch');
await fetchData();
console.timeEnd('fetch'); // fetch: 234ms

// Tables
console.table([{ name: 'Alice', age: 30 }, { name: 'Bob', age: 25 }]);

// Assert
console.assert(count > 0, 'Count must be positive');

// Stack trace
console.trace('Trace point');
```

#### Source Maps

Ensure source maps are enabled for readable stack traces:

```json title="app.json" theme={null}
{
  "expo": {
    "packagerOpts": {
      "sourceExts": ["js", "jsx", "ts", "tsx"],
      "sourceMaps": true
    }
  }
}
```

### React DevTools

Inspect React component tree, props, and state.

<Steps>
  <Step title="Install React DevTools">
    ```bash theme={null}
    npm install -g react-devtools
    ```
  </Step>

  <Step title="Start React DevTools">
    ```bash theme={null}
    # In a separate terminal
    react-devtools
    ```

    A standalone window opens.
  </Step>

  <Step title="Connect to app">
    ```bash theme={null}
    # Start your app
    npx expo start --dev-client
    ```

    React DevTools automatically connects to your running app.
  </Step>

  <Step title="Inspect components">
    * **Components tab**: View component hierarchy
    * **Profiler tab**: Measure render performance
    * Select components to inspect props and state
    * Edit props/state in real-time
  </Step>
</Steps>

#### Component Inspection

```typescript title="app/components/UserProfile.tsx" theme={null}
import { useState } from 'react';

export function UserProfile({ userId }: { userId: string }) {
  const [loading, setLoading] = useState(false);
  const [user, setUser] = useState(null);
  
  // In React DevTools:
  // - See UserProfile in component tree
  // - Inspect props: { userId: "123" }
  // - Inspect state: { loading: false, user: null }
  // - Edit values and see instant updates
  
  return <Text>{user?.name}</Text>;
}
```

#### Performance Profiling

```typescript theme={null}
import { Profiler } from 'react';

function onRenderCallback(
  id: string,
  phase: 'mount' | 'update',
  actualDuration: number,
  baseDuration: number,
  startTime: number,
  commitTime: number
) {
  console.log(`${id} ${phase} took ${actualDuration}ms`);
}

export default function App() {
  return (
    <Profiler id="App" onRender={onRenderCallback}>
      <Navigation />
    </Profiler>
  );
}
```

## Network Debugging

### Network Inspector

`expo-dev-client` includes a built-in network inspector.

<Steps>
  <Step title="Enable network inspection">
    Open dev menu and select "Network Inspector".
  </Step>

  <Step title="View requests">
    See all HTTP requests:

    * URL and method
    * Status code and timing
    * Headers and body
    * Response data
  </Step>

  <Step title="Inspect request details">
    ```typescript theme={null}
    // All fetch requests are automatically captured
    const response = await fetch('https://api.example.com/users');
    const data = await response.json();

    // View in Network Inspector:
    // - Request headers
    // - Response headers  
    // - Response body
    // - Timing information
    ```
  </Step>
</Steps>

### Network Debugging Tools

```typescript title="utils/api.ts" theme={null}
// Add request interceptor for debugging
const originalFetch = global.fetch;

global.fetch = async (input, init) => {
  const start = Date.now();
  console.log('→', init?.method || 'GET', input);
  
  try {
    const response = await originalFetch(input, init);
    const duration = Date.now() - start;
    
    console.log('←', response.status, input, `${duration}ms`);
    return response;
  } catch (error) {
    console.error('✗', input, error);
    throw error;
  }
};
```

### Proxying Requests

For debugging with tools like Charles or Proxyman:

```typescript title="app.json" theme={null}
{
  "expo": {
    "packagerOpts": {
      "dev": true
    },
    "ios": {
      "networkInspector": true
    }
  }
}
```

```bash theme={null}
# Set proxy on device
# iOS: Settings > WiFi > Configure Proxy > Manual
# Android: Settings > WiFi > Modify Network > Proxy > Manual
```

## Element Inspector

Visually inspect and debug UI elements.

<Steps>
  <Step title="Enable inspector">
    Shake device or press:

    * iOS: `Cmd+D`
    * Android: `Cmd+M`

    Select "Show Element Inspector".
  </Step>

  <Step title="Inspect elements">
    Tap any UI element to see:

    * Component name
    * Props
    * Styles
    * Layout dimensions
    * Position in hierarchy
  </Step>

  <Step title="Navigate hierarchy">
    Use breadcrumbs to navigate up the component tree.
  </Step>
</Steps>

### Style Debugging

```typescript title="app/components/Card.tsx" theme={null}
import { StyleSheet } from 'react-native';

export function Card({ children }: { children: React.ReactNode }) {
  return (
    <View style={styles.container}>
      {children}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 16,
    backgroundColor: '#fff',
    borderRadius: 8,
    // In inspector, see computed styles:
    // - padding: 16
    // - backgroundColor: "rgb(255, 255, 255)"
    // - borderRadius: 8
  },
});
```

## Native Debugging

### iOS with Xcode

Debug native iOS code and crashes.

<Steps>
  <Step title="Open in Xcode">
    ```bash theme={null}
    # Open workspace
    open ios/YourApp.xcworkspace

    # Or from CLI
    npx expo run:ios
    ```
  </Step>

  <Step title="Set native breakpoints">
    ```swift title="ios/YourApp/AppDelegate.swift" theme={null}
    import ExpoModulesCore

    @UIApplicationMain
    class AppDelegate: ExpoAppDelegate {
      override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
        // Set breakpoint here
        print("App launched")
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
      }
    }
    ```
  </Step>

  <Step title="View console output">
    In Xcode:

    * View > Debug Area > Show Debug Area (`Cmd+Shift+Y`)
    * See native logs and crashes
  </Step>

  <Step title="Debug memory issues">
    ```bash theme={null}
    # Run with memory debugging
    Product > Scheme > Edit Scheme > Run > Diagnostics
    # Enable: Address Sanitizer, Zombie Objects
    ```
  </Step>
</Steps>

### Android with Android Studio

Debug native Android code.

<Steps>
  <Step title="Open in Android Studio">
    ```bash theme={null}
    # Open project
    studio android/

    # Or from CLI
    npx expo run:android
    ```
  </Step>

  <Step title="Attach debugger">
    1. Run > Attach Debugger to Android Process
    2. Select your app process
    3. Choose "Java" debugger
  </Step>

  <Step title="Set native breakpoints">
    ```kotlin title="android/app/src/main/java/com/yourapp/MainApplication.kt" theme={null}
    import expo.modules.ApplicationLifecycleDispatcher

    class MainApplication : Application() {
      override fun onCreate() {
        super.onCreate()
        // Set breakpoint here
        Log.d("YourApp", "App started")
      }
    }
    ```
  </Step>

  <Step title="View Logcat">
    View > Tool Windows > Logcat

    Filter by your package:

    ```
    package:com.yourapp
    ```
  </Step>
</Steps>

### Debugging Native Modules

When working with Expo modules:

```swift title="ios/Modules/MyModule/MyModule.swift" theme={null}
import ExpoModulesCore

public class MyModule: Module {
  public func definition() -> ModuleDefinition {
    Name("MyModule")
    
    Function("doSomething") { (value: String) -> String in
      // Set breakpoint here to debug
      print("Native method called with: \(value)")
      return "Result: \(value)"
    }
  }
}
```

```kotlin title="android/src/main/java/expo/modules/mymodule/MyModule.kt" theme={null}
package expo.modules.mymodule

import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition

class MyModule : Module() {
  override fun definition() = ModuleDefinition {
    Name("MyModule")
    
    Function("doSomething") { value: String ->
      // Set breakpoint here to debug
      Log.d("MyModule", "Native method called with: $value")
      "Result: $value"
    }
  }
}
```

## Performance Debugging

### Performance Monitor

Enable the performance overlay:

```bash theme={null}
# In dev menu
Show Performance Monitor
```

Displays:

* JavaScript frame rate
* UI frame rate
* Memory usage
* Views count

### Profiling with Hermes

For better performance, use Hermes:

```json title="app.json" theme={null}
{
  "expo": {
    "jsEngine": "hermes"
  }
}
```

Profile with Chrome DevTools:

```bash theme={null}
# Start with profiling
npx expo start --dev-client

# Open chrome://inspect
# Click "inspect" next to Hermes
# Go to "Performance" tab
# Record and analyze
```

### React Native Performance

```typescript theme={null}
import { InteractionManager } from 'react-native';

// Defer expensive operations
InteractionManager.runAfterInteractions(() => {
  // Expensive operation after animations
  processLargeDataset();
});

// Track slow renders
const onRender = (id, phase, actualDuration) => {
  if (actualDuration > 16) { // Slower than 60fps
    console.warn(`Slow render: ${id} took ${actualDuration}ms`);
  }
};
```

## Troubleshooting

### Debugger Won't Connect

```bash theme={null}
# Check Metro is running
lsof -i :8081

# Restart Metro
npx expo start --dev-client --clear

# Try different host
npx expo start --dev-client --host tunnel
```

### Source Maps Not Working

```bash theme={null}
# Clear Metro cache
npx expo start --clear

# Rebuild
npx expo run:ios --clean
npx expo run:android --clean
```

### Performance Issues in Debug Mode

Debug mode is slower than production:

```bash theme={null}
# Test performance in release mode
npx expo run:ios --configuration Release
npx expo run:android --variant release
```

### Xcode: Process Launch Failed

```bash theme={null}
# Clean build folder
cd ios
xcodebuild clean
rm -rf ~/Library/Developer/Xcode/DerivedData

# Rebuild
cd ..
npx expo run:ios --clean
```

## Next Steps

<CardGroup cols={2}>
  <Card title="DevTools" icon="wrench" href="/development/devtools">
    Explore Expo DevTools and plugins
  </Card>

  <Card title="Inspector" icon="magnifying-glass" href="/development/inspector">
    Use the element inspector
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation" href="/development/errors">
    Handle errors and crashes
  </Card>

  <Card title="Testing" icon="flask" href="/development/unit-testing">
    Set up automated testing
  </Card>
</CardGroup>
