Skip to content

[Bug]: getDeviceIdAsync callback never fires on a significant share of app launches #115

Description

@thkim9373

Braze Android SDK Version

42.3.1

Steps To Reproduce

The issue is probabilistic, so a deterministic minimal reproduction is not available. Below is the call pattern and how we measured it.

  1. During application startup (an androidx.startup Initializer, once per process), request the device ID:

    suspend fun getBrazeDeviceIdAwait(): String {
        return suspendCancellableCoroutine { cont ->
            Braze.getInstance(context).getDeviceIdAsync(object : IValueCallback<String> {
                override fun onSuccess(value: String) { cont.resume(value) }
                override fun onError() { /* logged; never invoked in these cases */ }
            })
        }
    }

    Braze.configure(...) always runs before this call — the initializer above is ordered after our Braze setup initializer via androidx.startup dependency ordering, so the SDK configuration is complete at the time of the call.

  2. Start a timer at the call site. If neither onSuccess nor onError arrives within 5 seconds, record it.

  3. If a callback arrives later, record it with the elapsed time (only when it exceeds 3 seconds).

  4. Include the values of Braze.isSdkDisabledOrDelayed and Braze.isDisabled in each record.

  5. Collect the records from production for 3 days.

Pattern: the issue is most prominent on cold starts where the process is launched in the background (e.g., triggered by an FCM message). Once a process fails to receive a callback, every subsequent call within that same process lifetime fails consistently.

Expected Behavior

Per the getDeviceIdAsync API documentation, the device ID is "a randomly generated, app specific ID that is stored on the device". We expect the callback to arrive within a short time.

Actual Incorrect Behavior

On affected launches, the callback never arrives within the lifetime of the process. Of the calls with no callback within 5 seconds, approximately 95% never received one at all.

Measured over 3 days in a production app with millions of DAU, by unique devices that launched the app:

Result % of devices that launched the app
At least one launch where the callback never arrived 27.1%
Callback arrived with a delay of 3+ seconds 3.1%

When the callback did arrive late, the elapsed time was p50 3.9s / p90 10.3s for foreground launches, and p50 7.7s / p90 68s including background launches (elapsed time includes periods of Doze / app freezing).

Every no-callback record had isSdkDisabledOrDelayed=false and isDisabled=false.

Verbose Logs

Braze verbose logs from an affected device are not available — the issue is
probabilistic and occurs on production devices where verbose logging is not
enabled.

Our own instrumentation records the following for each affected call:

getDeviceIdAsync watchdog: no callback within 5s
- elapsed = 5002ms
- isSdkDisabledOrDelayed = false
- isDisabled = false
(caller: app startup initializer, BackgroundMode=true, NetworkType=Wi-Fi)

If verbose logs would help, let us know what to capture and we will try to
obtain them.

Additional Information

As a mitigation, we plan to cache the first successfully received value locally in the app, apply a timeout to the wait, and fall back to the cached value on timeout. Are there any potential caveats or risks with this approach? The API documentation states the ID regenerates only when app data is cleared or the app is reinstalled — are there any other cases where the value changes (e.g., SDK upgrades)?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions