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

# Troubleshooting

> Common issues and solutions for the React Native SDK

# Troubleshooting

Common issues and solutions when using Superflag in React Native and Expo.

## App Crashes in Production

### Symptom

App works fine in development but crashes immediately on launch in TestFlight or production builds.

### Solution

**Quick checklist:**

1. Using public key (`pub_*`), not server key?
2. AsyncStorage installed?
3. Built with a production build locally?

```bash theme={null}
# Test with production build
eas build --platform ios --profile preview
```

## AsyncStorage Not Found

### Symptom

```
Error: @RNC/AsyncStorage: NativeModule: AsyncStorage is null
```

### Solution

Install AsyncStorage:

```bash theme={null}
npx expo install @react-native-async-storage/async-storage
```

For bare React Native:

```bash theme={null}
npm install @react-native-async-storage/async-storage
cd ios && pod install
```

## Flags Not Loading

### Symptom

`useFlags()` shows `status: 'loading'` forever, or `status: 'error'`.

### Solution

<Tabs>
  <Tab title="Check Client Key">
    Ensure you're using a valid public client key (`pub_*`):

    ```tsx theme={null}
    const { error } = useFlags()
    console.log('Error:', error)  // Check what error is
    ```

    Common issues:

    * Using wrong key (server key instead of public key)
    * Environment variable not set
    * Typo in key
  </Tab>

  <Tab title="Check Network">
    Ensure your app can reach `https://superflag.sh`:

    ```tsx theme={null}
    // Test network connectivity
    fetch('https://superflag.sh/api/v1/public-config', {
      headers: {
        Authorization: `Bearer ${process.env.EXPO_PUBLIC_SUPERFLAG_CLIENT_KEY}`
      }
    })
      .then(res => console.log('Status:', res.status))
      .catch(err => console.error('Network error:', err))
    ```
  </Tab>

  <Tab title="Check Environment Variables">
    For Expo, ensure you're using `EXPO_PUBLIC_` prefix:

    ```bash .env theme={null}
    # ✅ Correct
    EXPO_PUBLIC_SUPERFLAG_CLIENT_KEY=pub_...

    # ❌ Wrong
    SUPERFLAG_CLIENT_KEY=pub_...
    ```

    Restart dev server after changing `.env`:

    ```bash theme={null}
    npx expo start --clear
    ```
  </Tab>
</Tabs>

## Rate Limited

### Symptom

`status: 'rate-limited'` or error message "Monthly quota exceeded".

### Solution

You've hit your plan's monthly request limit. The SDK will continue using cached flags.

**To resolve:**

1. Increase cache TTL to reduce requests:
   ```tsx theme={null}
   <SuperflagProvider ttlSeconds={300}> {/* 5 minutes */}
   ```

2. Upgrade your plan in the dashboard

3. Check for request loops:
   ```tsx theme={null}
   // ❌ Don't do this - infinite loop
   useEffect(() => {
     client.refetch()  // Called on every render
   })

   // ✅ Do this - call only when needed
   const handleRefresh = () => {
     client.refetch()
   }
   ```

## Slow Initial Load

### Symptom

App shows loading state for several seconds on first launch.

### Solution

This is expected on first launch. The SDK fetches flags and caches them. Subsequent launches are instant.

**To improve first launch:**

1. Show cached content while loading:
   ```tsx theme={null}
   const { ready } = useFlags()
   const feature = useFlag('feature', false)

   // Don't wait for ready - use cached/fallback values immediately
   return <View>{feature && <Feature />}</View>
   ```

2. Preload flags before mounting:
   ```tsx theme={null}
   // app/_layout.tsx
   import { useFlags } from '@superflag-sh/react-native'
   import { SplashScreen } from 'expo-splash-screen'

   SplashScreen.preventAutoHideAsync()

   export default function Layout() {
     const { ready } = useFlags()

     useEffect(() => {
       if (ready) {
         SplashScreen.hideAsync()
       }
     }, [ready])

     return <Slot />
   }
   ```

## TypeScript Errors

### Symptom

TypeScript can't find types or shows errors for SDK exports.

### Solution

The SDK includes types out of the box. If you're getting errors:

1. Ensure you're on TypeScript 5.0+:
   ```bash theme={null}
   npm list typescript
   ```

2. Add to `tsconfig.json`:
   ```json theme={null}
   {
     "compilerOptions": {
       "moduleResolution": "bundler",
       "skipLibCheck": true
     }
   }
   ```

3. Restart TypeScript server in VS Code:
   * Cmd+Shift+P → "TypeScript: Restart TS Server"

## Cache Not Persisting

### Symptom

Flags reload from network every time app launches, even when cache should be valid.

### Solution

Check AsyncStorage is working:

```tsx theme={null}
import AsyncStorage from '@react-native-async-storage/async-storage'

// Test AsyncStorage
AsyncStorage.setItem('test', 'value')
  .then(() => AsyncStorage.getItem('test'))
  .then(value => console.log('AsyncStorage works:', value === 'value'))
  .catch(err => console.error('AsyncStorage error:', err))
```

If AsyncStorage isn't working:

1. Reinstall: `npx expo install @react-native-async-storage/async-storage`
2. For bare RN: `cd ios && pod install`
3. Clear build cache: `npx expo start --clear`

## Expo Updates ErrorRecovery Crash

### Symptom

Crash log shows `ErrorRecovery.notify` or mentions expo-updates.

### Solution

This means expo-updates detected an error during app startup and crashed to prevent a bad update from "bricking" your app.

## Still Having Issues?

If none of these solutions work:

1. **Check the example app** in the [GitHub repo](https://github.com/superflag-sh/react-native/tree/main/example)

2. **Enable debug logging**:
   ```tsx theme={null}
   const { status, error, version } = useFlags()
   console.log('Status:', status)
   console.log('Error:', error)
   console.log('Version:', version)
   ```

3. **Test with a minimal reproduction**:
   ```tsx theme={null}
   import { SuperflagProvider, useFlag } from '@superflag-sh/react-native'

   export default function App() {
     return (
       <SuperflagProvider clientKey="pub_...">
         <Test />
       </SuperflagProvider>
     )
   }

   function Test() {
     const flag = useFlag('test', false)
     return <Text>{String(flag)}</Text>
   }
   ```

## Next Steps

<CardGroup cols={2}>
  <Card title="Usage Guide" icon="code" href="/react-native/usage">
    Learn how to use the SDK
  </Card>

  <Card title="API Reference" icon="book" href="/react-native/api-reference">
    Complete API documentation
  </Card>
</CardGroup>
