Common problems
The app throws a Reanimated error on startup
The app throws a Reanimated error on startup
[Reanimated] Couldn't determine the version of the native part of Reanimated mean the Babel plugin is missing or the app was not rebuilt.Fix: add react-native-reanimated/plugin as the last plugin in babel.config.js, then do a clean start:npx expo prebuild and rebuild the native app. See Installation.`Unable to resolve module expo-...`
`Unable to resolve module expo-...`
npx expo install (not plain npm install, so versions match your Expo SDK):Nothing shows when I present a placement
Nothing shows when I present a placement
- The SDK is not configured. If
FlowPilot.configure(...)never ran (or threw on a bad key and the throw was swallowed), every present resolves to anerroroutcome with codeSDK_NOT_INITIALIZED. Check the debug log for the configure line. - Wrong App ID. The flow, placement, and key must all belong to the same app. A mismatched
appIdresolves against the wrong app and finds nothing. - The placement has no flow for this user. The placement may be paused, have no default flow attached, or exclude this user by audience targeting. The resolve returns
FLOW_NOT_FOUND. This is expected, not a bug. Check the placement in the dashboard. See Placements and Audience targeting. - The flow is a draft, or is not attached. Only a published flow attached to the placement is served. Publishing alone does not attach it. See Publishing.
- The platform excludes this app. A placement gates which platforms it serves.
- Offline with a cold cache. With no network, no cached flow, and no bundled default, there is nothing to present.
'debug' logging and read which step fails. For anything user-facing, use the resilient path so the user always sees something:`configure` throws, or every present is SDK_NOT_INITIALIZED
`configure` throws, or every present is SDK_NOT_INITIALIZED
FlowPilot.configure(...) validates synchronously and throws on a bad input:Invalid API key. Must start with "fp_".TheapiKeyis wrong or unset.App ID is required.TheappIdis empty.
configure in an empty catch, the SDK stays unconfigured and every later present throws SDK_NOT_INITIALIZED.Fix: call configure exactly once, as early as possible, with a valid key and app id, and let any thrown error surface during development. See Configuration.`TIMEOUT` or very slow first present on poor networks
`TIMEOUT` or very slow first present on poor networks
resolveTimeout (default 4s) and there was nothing cached or bundled to fall back to.Fixes, in order of impact:- Ship a bundled default flow so the first present always has something offline. See Offline and bundled flows.
- Prefetch at launch so the placement is warm before the user reaches it:
prefetchOnLaunch: ['onboarding'], orawait FlowPilot.prefetch(['onboarding'])(add{ warmMedia: true }for first-screen images). See Prefetching. - Use
resolveSessionso a timeout falls through to cache, then bundled, then your own UI instead of an error. - Raise
resolveTimeoutonly if your audience is on consistently slow networks. It bounds the whole resolve; the minimum is0.5.
A component renders blank (`CUSTOM_COMPONENT_NOT_FOUND`)
A component renders blank (`CUSTOM_COMPONENT_NOT_FOUND`)
- Not registered. You never called
registerCustomComponent, or registered it after presenting. Register before you present. - Key mismatch. The
keyyou registered does not match the component key in the flow exactly (case-sensitive). - Version mismatch. The SDK matches on
key + version. If the flow uses version2and you registered version1, it will not match.
A component shows a 'Not supported' / unknown placeholder
A component shows a 'Not supported' / unknown placeholder
Fonts look wrong or fall back to the system font
Fonts look wrong or fall back to the system font
- The font was not uploaded. Custom fonts must be uploaded to the workspace so the resolve response includes them. See Custom fonts.
- Family, weight, or style mismatch. The flow references a variant that does not exist among the uploaded fonts, so it falls back to the system font.
- Offline with no bundled font assets. A bundled (offline) flow only has its fonts when you ship them in the asset bundle. Without a
fontsentry in the.flowassetsmanifest, an offline render uses the system font. expo-fontmissing. Without it, custom fonts cannot register. Confirm it is installed.
Images do not load when offline
Images do not load when offline
- No bundled assets. A bundled default flow with no image assets shows blank images offline. Ship the images in the
.flowassetsbundle so the SDK seeds the image cache before first paint. - Cold cache. If the user has never seen the flow online, nothing is cached. Preload or prefetch while the network is available.
The flow renders under the status bar or home indicator
The flow renders under the status bar or home indicator
react-native-safe-area-context. Without a provider, useSafeAreaInsets() returns zeros.Fix: wrap your app in <SafeAreaProvider> and pass safeAreaInsets={useSafeAreaInsets()} to <FlowPilotPresenter />. See Installation.I republished the flow but the app still shows the old version
I republished the flow but the app still shows the old version
- Cache TTL. The SDK serves a fresh cached flow without hitting the network until it goes stale (the resolve response’s
cacheTtlSeconds, or the environment default). CallFlowPilot.clearCache()to force a re-resolve during testing. - The placement still points at the old version. Publishing a new version does not automatically repoint a placement. Until you attach the new version, the resolve keeps returning the old one. This is the most common cause. See Publishing.
An experiment user keeps switching variants
An experiment user keeps switching variants
expo-secure-store, so it normally survives restarts. Switching usually means that id is being reset: a reinstall, cleared secure store, or testing across multiple devices. There is no public API to set a custom user id in this build, so you cannot pin it yourself yet.Fix: test variant stickiness on a persistent device/simulator without resetting it between launches. Confirm expo-secure-store is installed so the id persists. See Variables and context and Reading experiment results.Events not appearing in the dashboard
Events not appearing in the dashboard
- Force-quit before the flush timer. Queued events persist to disk and replay on next launch; they are not lost.
- Network error after retries. A batch is retried 3 times, then dropped (visible as a
Logger.warnline). - Missing
expo-file-system. On-disk persistence needs it. Confirm it is installed.
logLevel: 'debug' to see batch flushes. Background the app to force an immediate flush during testing. See Analytics.When you cannot reproduce it
- Test the resilient path. Turn on Airplane Mode and present. With
resolveSession(or the presenterfallback) and a bundled flow, the user should still see something. A blank screen means a missing bundled default or its assets. - Confirm the delivery source. The
delivery_sourceon analytics events (and the debug logs) tells you whether a render came from the network, cache, stale cache, or bundled default. A surprising source often explains a surprising flow. - Check the dashboard first. Most “nothing shows” cases are a paused placement, an unattached flow, or a targeting rule, not an SDK bug.