Troubleshooting

What the common symptoms mean and how to fix them, from a start that fails to pushes and geofences that don't arrive.

Start with Bubbl.diagnostics() and Bubbl's own log: see Testing and diagnostics. Most problems show up in active, registered, hasPushToken or lastError.

Turn on debug logs#

Bubbl only logs warnings and errors by default. To see everything it does, start it with logLevel set to debug while you investigate, then set it back:

KOTLIN
BubblOptions(baseUrl = "https://api.bubbl.tech", logLevel = BubblOptions.LogLevel.DEBUG)
SWIFT
BubblOptions(baseUrl: "https://api.bubbl.tech", logLevel: .debug)
DART
const BubblOptions(baseUrl: 'https://api.bubbl.tech', logLevel: BubblLogLevel.debug)
TS
{ baseUrl: 'https://api.bubbl.tech', logLevel: 'debug' }

Bubbl logs natively, also from Flutter and React Native apps:

  • Android: Logcat, tag BubblSDK.
  • iOS: the unified log, subsystem tech.bubbl.sdk: the Xcode console, or Console.app filtered on the subsystem.

With debug on, you'll see lines such as:

  • Geofence check: each time Bubbl decides whether to fetch geofences, with the result (Updated, Unchanged or NotDue), or no location fix when the phone has no position.
  • Watching N geofences with Play services on Android, once the geofences are set.
  • Geofence entry sent: N notification(s) to show (or exit) when the phone crosses a geofence.
  • Since 5.0.1, The Bubbl server answered HTTP … to … requests in a row when the server keeps failing (3 requests in a row). This one is an error, so it shows at the default level too.

Leave debug off in release builds.

Bubbl doesn't start#

SymptomCause and fix
Bubbl.start: the API key is emptyPass the SDK API key from Configuration › Developers.
Bubbl.start: baseUrl must be https:// (http:// only for localhost or a .test host)Use the https:// API address. http:// is only for local development: see Local development over http.
Bubbl.start: the credential is incompleteThe key ID, secret or install ID of a device credential is empty.
supported falseThe device is below Android 8.1 or iOS 17. Bubbl stays inactive there by design.

On Android, the native Bubbl.start throws these as an IllegalArgumentException, so they show as a crash in development. On iOS, and in Flutter and React Native, they're logged and Bubbl doesn't start.

The device doesn't register#

SymptomCause and fix
registered stays false and lastError says The Bubbl server answered HTTP 5xx to 3 requests in a row…Bubbl's server is having problems, not your app. Bubbl keeps retrying and recovers by itself; check status.bubbl.tech. Since 5.0.1: before, lastError stayed empty during an outage.
registered stays false and lastError mentions invalid_keyThe API key is wrong: a typo, or another workspace's. Copy it again from Configuration › Developers.
Bubbl logs that the API key and the address don't match (wrong_environment) and stopsA pk_live_ key needs https://api.bubbl.tech. The log says which address to use. A pk_test_ key belongs to a Sandbox, which isn't open on production. See Plans and going live.
iOS: The app can't use the Keychain (errSecMissingEntitlement)The build isn't code-signed (for example a Simulator build with signing turned off), and iOS gives an unsigned app no Keychain. Sign the build.
iOS: An http:// baseUrl needs NSAllowsLocalNetworking…App Transport Security blocks local http://. In development builds only, set NSAppTransportSecurity › NSAllowsLocalNetworking to YES.

Registered, but nothing arrives#

SymptomCause and fix
registered stays false, active false, pausedUntil set, and the server answered own_app_not_in_planYour company is on the Free plan, which doesn't include your own app. Subscribe to a paid plan: Bubbl tries again after 24 hours. See Plans and going live.
active false, consentRequired true, consent nullYou started with requireConsent. Call setConsent(true) once the user agrees.
active false, consent falseThe user opted out, or deleteMyData() was called.
active false, pausedUntil setThe server paused Bubbl, for example because your plan doesn't include your own app (own_app_not_in_plan). It retries later. Check your plan under Billing.
sdkSupported false, and This SDK (…) is older than the workspace's minimum in the logYour workspace requires a newer SDK. Update it.
credentialRejected trueThe server refused the device credential (it was revoked, for example). Bubbl has stopped: start it with a new credential.

Push#

SymptomCause and fix
Android: hasPushToken false on the first launch onlyNormal with the dashboard's google-services.json: Bubbl gets the Firebase settings when it first registers, and the token on the next launch or within the hour. Don't upload the file again.
Android: hasPushToken stays falseNo Firebase: upload google-services.json under Configuration › Push › Android apps, or add it to the app together with the com.google.gms.google-services Gradle plugin (the file alone is ignored). Check your package name is in it.
Android: a token, but no pushes and no errorYour app's Firebase project isn't the one whose service account is in the dashboard. They must match.
Android: nothing after the user force-stopped the appAndroid wakes no app after a force stop until it's opened again.
Android: Notification not shown: the app is in the background and notifications are offThe user hasn't allowed notifications (Android 13 and later). Ask with Bubbl.permissions.requestNotifications().
iOS: hasPushToken falseNotifications aren't allowed yet. Bubbl asks iOS for the token once they are, at the latest the next time the app opens.
iOS: iOS couldn't give the app a device token …Usually the Push Notifications capability or the provisioning profile is missing.
iOS: The app has no delegate, so Bubbl can't get the device tokenCall Bubbl.setPushToken from your app delegate. See Handing over pushes yourself.
iOS: pushes don't arriveCheck the bundle ID and key under Configuration › Push, and that the build's APNs environment matches: development-signed Xcode builds are sandbox; ad hoc, TestFlight and App Store builds are production.
iOS: pushes arrive without their pictureAdd the notification service extension, and replace Xcode's template code in it entirely. See Pictures on iOS pushes.
A push doesn't show on a phone with a push tokenactive must be true on the phone, and the device must not have opted out.

Geofences#

SymptomCause and fix
Geofences fire only with the app openThe user allowed location only while using the app (backgroundLocation false). Ask with requestLocation and always set to true.
iOS: osWatchesGeofences false"Always" with precise location is needed for iOS to watch geofences itself; otherwise they're checked from location changes, which is coarser.
Android: backgroundRestricted trueThe user restricted the app's background activity in Settings. Bubbl can't run with the app closed until they lift it.
geofences is 0See geofences is 0 below.
iOS: some events missing after a rebootEvents before the first unlock after a reboot can't be kept on iOS; transitionsDroppedWhileLocked counts them.

geofences is 0#

geofences in diagnostics() is how many geofences Bubbl got from its last fetch. It's 0 before the first fetch, and after a fetch that found nothing. It isn't how many the operating system is watching. Check these in order:

  1. Location. With location off for Bubbl (locationEnabled false) or no location permission, Bubbl doesn't fetch at all.
  2. Distance. Bubbl asks for the geofences within 5 km of the device, nearest first, and gets at most 50. A device more than 5 km from every campaign location gets none. On an emulator, give it a position near your locations: see Positions on emulators and simulators.
  3. The campaign. Only running geo campaigns are served: started, not paused and not ended, with at least one notification that's sent on entering or on leaving. A campaign with no notification attached, or one that hasn't started yet, adds nothing.
  4. The key. The SDK API key must be the workspace whose campaigns you expect. Another workspace's key sees none of them.
  5. Timing. The app fetches again every 15 minutes, or sooner once it has moved 2.5 km. A change to a campaign can take up to 5 minutes to reach the server's answers. Until then, the device keeps the set it last fetched, even an empty one.

To see each fetch on Android, turn on debug logs: Bubbl logs Geofence check: with Updated(geofences=…), Unchanged or NotDue (not time to fetch yet), or no location fix when the device has no position.

Flutter and React Native#

SymptomCause and fix
React Native: none of Bubbl's calls do anythingThe New Architecture is off, or the app wasn't rebuilt after installing the package. The package is a TurboModule only.
React Native: diagnostics() says started false with a reason in lastErrorThere's no native module here: Expo Go, the web build, Jest, or an old build. Use a development build.
Flutter or React Native: no Bubbl logs in the Dart or JavaScript consoleBubbl logs natively: Logcat (tag BubblSDK) or the iOS unified log (tech.bubbl.sdk).
Flutter iOS: Xcode reports a dependency cycle after adding the notification service extensionIn Runner › Build Phases, drag "Embed Foundation Extensions" above "Thin Binary".
Expo: prebuild fails on cleartextHostsYour app already has a network security config. Add the hosts to it and leave android.cleartextHosts out.

Still stuck? Collect Bubbl.diagnostics() and the native log at debug level before contacting Bubbl support.