Upload source maps for React Native

CLI version requirement

A minimum CLI version of 0.7.8 is required, but we recommend keeping up with the latest CLI version to ensure you have all of error tracking's features.

React Native Web

If you are using React Native Web, ensure source maps are generated

Terminal
# example command
# Files are usually under the '$buildFolder/_expo/static/js/web' folder ($name.js and $name.js.map)
npx expo export --source-maps --platform web

Then use our standard CLI approach to inject and upload them.

  1. Download CLI

    Required

    Install posthog-cli:

    npm install -g @posthog/cli

  2. Authenticate

    Required

    To authenticate the CLI, call the login command. This opens your browser where you select your organization, project, and API scopes to grant:

    Terminal
    posthog-cli login

    If you are using the CLI in a CI/CD environment such as GitHub Actions, you can set environment variables to authenticate:

    Environment VariableDescriptionSource
    POSTHOG_CLI_HOSTThe PostHog host to connect to [default: https://us.posthog.com]Project settings
    POSTHOG_CLI_PROJECT_IDPostHog project IDProject settings
    POSTHOG_CLI_API_KEYPersonal API key with error tracking write and organization read scopesAPI key settings

    You can also use the --host option instead of the POSTHOG_CLI_HOST environment variable to target a different PostHog instance or region. For EU users:

    Terminal
    posthog-cli --host https://eu.posthog.com [CMD]

  3. Inject

    Required
    Expo 50 or later

    Automatic source map injection works only in React Native apps using Expo 50 or later, as it relies on Expo’s built-in debug ID injection.

    Create or update the metro.config.js file in your app's root directory so that it looks like this:

    diff
    -const { getDefaultConfig } = require("expo/metro-config");
    +const { getPostHogExpoConfig } = require('posthog-react-native/metro')
    -const config = getDefaultConfig(__dirname);
    +const config = getPostHogExpoConfig(__dirname)
    module.exports = config
  4. Upload

    Required

    Automatic source map uploading is handled through the Gradle build process on Android and the Xcode build process on iOS.

    EAS Updates

    If you are using EAS Updates, source maps must be uploaded manually after running the update command. The automatic upload via Gradle/Xcode only runs during native builds, not during OTA updates.

    Terminal
    # After running `eas update` or `npx expo export --dump-sourcemap`, upload source maps from the output directory
    posthog-cli hermes upload --directory dist

    The dist folder is the default output directory for EAS updates.

    1. Expo: Update the app.json file in your app's root directory.

    Expo Plugins that add modifications can only be used with prebuilding and managed EAS Build.

    If you can use the posthog-react-native/expo plugin, skip steps 2 and 3. If not, proceed with steps 2 and 3.

    Add the posthog-react-native/expo plugin under the expo.plugins.

    diff
    {
    "expo": {
    ...
    "plugins": [
    ...
    + "posthog-react-native/expo"
    ]
    }
    }

    The plugin accepts the following options:

    OptionTypeDefaultDescription
    disableSandboxingbooleantrueiOS only. When true, sets ENABLE_USER_SCRIPT_SANDBOXING=NO on your main app target's Xcode build configurations during expo prebuild. This lets the source map upload script read .git/ (for release metadata) and lets stock Expo projects build without manually declaring input/output files on every script phase.

    Example opting out of the sandbox change:

    JSON
    {
    "expo": {
    "plugins": [
    ["posthog-react-native/expo", { "disableSandboxing": false }]
    ]
    }
    }
    When to opt out

    disableSandboxing: false is intended for organizations with compliance requirements that forbid disabling Xcode's user script sandbox. With the opt-out:

    • iOS source map uploads continue to work — errors still symbolicate
    • Git metadata will not be attached to iOS releases (the UI chip shown for Android rows will be missing on iOS rows)
    • Your project must already have every build-phase script (yours, Expo's, CocoaPods-generated) declaring its inputs and outputs, otherwise the build will fail

    This setting only affects build-time scripts on the build machine. Your shipped app's runtime security is unchanged.

    1. Android: Update the /android/app/build.gradle file from your app's root directory so that it looks like this:
    diff
    ...
    // This must be placed directly above the following `android` block.
    +apply from: new File(["node", "--print", "require('path').join(require('path').dirname(require.resolve('posthog-react-native')), '..', 'tooling', 'posthog.gradle')"].execute().text.trim())
    android {
    ...
    }
    1. iOS: Update the /ios/$yourProjectName.xcodeproj/project.pbxproj file (replace $yourProjectName with your project's actual name). You need to locate the Bundle React Native code and images build step.

    To do this through Xcode, open your project in Xcode, go to the project settings, navigate to Build Phases, select Bundle React Native code and images, and apply the changes shown below.

    diff
    ...
    -`"$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'"`
    +/bin/sh `"$NODE_BINARY" --print "require('path').join(require('path').dirname(require.resolve('posthog-react-native')), '..', 'tooling', 'posthog-xcode.sh')"` `"$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'"`

    If you are not using the Expo plugin (step 1), you will need to also disable User Script Sandboxing for the upload script to work. In Xcode, go to Build Settings, search for User Script Sandboxing (ENABLE_USER_SCRIPT_SANDBOXING) and set it to No. This is required because the script needs to read .git/ for release metadata and execute posthog-cli, which are not allowed under Xcode's script sandbox.

  5. Verify source maps upload

    Checkpoint
    Confirm that source maps are successfully uploaded to PostHog.Check symbol sets in PostHog

Troubleshooting

Build fails with Sandbox: bash deny(1) file-read-data

You probably have { disableSandboxing: false } set in your plugin options, or your Xcode project has ENABLE_USER_SCRIPT_SANDBOXING = YES set explicitly somewhere that overrides the plugin. Stock Expo projects need the sandbox disabled because several build-phase scripts (Expo's expo-configure-project.sh, various CocoaPods-generated scripts) don't declare all their inputs. Either remove the opt-out, or declare inputs on every script phase and keep sandboxing on.

Community questions

Was this page useful?

Questions about this page? or post a community question.