Reference
Troubleshooting
Symptoms first, then the likely cause. Start with bugcapsule inspect <id>: eligibility gaps and replay divergences usually name the problem.
Capture and upload
Nothing shows up in bugcapsule list
- Capture settings not fetched yet. Uploads wait until they are. Check the device can reach your API URL (proxies, firewalls, a typo in the URL).
- Session not sampled. In
productionmode only ~10% of sessions record. The web SDK defaults to production; setmode: 'qa'. - No
backendin the SDK config: captures are saved locally only. - Kill switch on:
bugcapsule captureshowsenabled: false. - Wrong key: a
bcs_key in the app, or a rotatedbci_key. A rejected key stops capture for the session (Flutter and web also delete the local queue). - Crash capsules upload on the next launch (Android, iOS). Reopen the app.
- iOS:
BugCapsule.instrument(config)withoutBugCapsuleURLSessioninintegrationsrecords no network. Uploads only run in the foreground. - Android: missing
INTERNETpermission.
Web: CORS errors in the browser console
Your app's origin isn't allowed for your project yet. Send the exact origin (scheme, host and port) to your BugCapsule team; see Get your origin allowed.
Some capsules never arrive
- The capsule is larger than the project's maximum capsule size (5 MB by default; see the dashboard's capture settings). Lower
maxBodyBytesor exclude large endpoints. - A custom integration or
beforeRecordhook writes values that aren't plain JSON, so the capsule is rejected. Check withbugcapsule inspecton the saved local file. - The device is offline or BugCapsule is briefly busy: the SDK keeps the capsule in its outbox and retries for up to 7 days.
Capsule is partial
build.gitSha: build withoutBUGCAPSULE_GIT_SHA(Flutter dart-define, Android Gradle property/meta-data, iOS Info.plist keys, web env), or a dirty tree.- Missing bodies: body capture off, excluded endpoints, bodies over the limit.
crash.persisted: written by a crash handler; expected for crashes.capability.input.pointer.replayon iOS: pointer-only flows. Add semantic actions.
Capsule is ineligible
A manual capture without a failure assertion. Add check/fail for the behaviour QA reports, so the capsule has something replay can check.
A secret showed up in a capsule
Delete the capsule in the dashboard, add the field name to Extra redaction keys in the dashboard's capture settings (it reaches every device at its next refresh and also re-redacts what's already buffered), then add it to your app's redactKeys or a beforeRecord hook. Rotate the leaked secret itself.
Replay
INCONCLUSIVE with network.unrecorded
- A volatile field (timestamp, nonce, request id) is part of the request key: add an
EndpointRulewithignoreBodyFields/ignoreQuery. - Your fix changes which requests the app sends: strict replay can't prove a fix it never saw. Capture a capsule on the fixed path. This is correct behaviour, not a bug.
- The replayed build talks to a different host or path (environment config).
action.unregistered or text.untracked
The replayed build doesn't register an id the recording used: renamed, registered later than the input, or behind a feature flag. Web: BugCapsule.action() registers its replay handler only after init.
restore.late or restore.missing
Init isn't first (Android: not at the top of Application.onCreate, or from an App Startup initializer; iOS: something read UserDefaults before start; web: rendering before await init). Or state is registered after the first input. Or the replayed build lacks an integration the capture had.
*.redacted divergences on a login flow
A token or OTP was replaced on device and replayed as a placeholder, so the app took another path. Use a QA test account whose credentials aren't needed in the failing flow, or start the flow after login.
INCOMPATIBLE
runtime.mismatch: wrong project; use-por--runtime.- State schema: the app's
stateSchemaVersiondiffers from the capsule's periodic checkpoint. Expected after a schema change; in regression suites the test becomesstale.
FLAKY on a race
Recorded latency is replayed exactly, but idle compression can skip over a timer whose effect wasn't recorded. Try --no-compress-idle. Replace DateTime.now()/Date.now()/Math.random() with the SDK hooks.
Runtime-specific
Android: attempts time out or never start
- The emulator must be unlocked once after boot; AVDs with a PIN can't be unlocked by the CLI.
testInstrumentationRunnerisn'tBugCapsuleReplayRunner, or the variant isn't debuggable (replay is refused).bootTimeoutSecondsinbugcapsule.jsonmust be a string ("300").
iOS: the app ignores replay
- The build configuration doesn't define
DEBUG(ios.configuration). replayTestdoesn't point at your test (<UITestTarget>/BugCapsuleReplayTests/testReplay); withoutuiTestTargetthe default target name isUITests.- Physical devices aren't supported by the launcher; use a simulator.
Web: the CLI refuses to start, or reports network.escaped
- Something already serves
web.url(maybe an old build). Stop it, or pass--app-urlto use it deliberately. allowReplayis false in the build the CLI serves; set it viaweb.env.- Requests to other origins (fonts, CDNs, analytics) are blocked: add static ones to
web.allowOrigins; make the SDK init before code that capturesfetch.
Flutter: pub get fails after adding the package
The package depends on every library it integrates with. Your app's bloc, riverpod, get, mobx, dio, http, go_router and shared_preferences versions must be inside its ranges even if you don't use them with BugCapsule.
Known limitations
- Not captured anywhere: WebSockets, platform channels and native SDKs, other HTTP stacks than the integrated ones, screenshots.
- Only the SDK clock and random hooks are deterministic.
- No consent, user-identify or breadcrumb APIs in any SDK. Use the local
enabledswitch,labels,logand actions. - No cross-runtime replay. No iOS pointer replay. Web replay in Chromium only.