Skip to content

Firebase.crashlytics.log() breadcrumb not attached to recordException() when called from background thread #8034

@RyeGordo

Description

@RyeGordo

Describe your environment

  • Android Studio version: Panda 3 | 2025.3.3
  • Firebase Component: Crashlytics
  • Component version: From firebase-bom:34.11.0

Describe the problem

Firebase.crashlytics.log() breadcrumbs are silently dropped when called from a background thread

When Firebase.crashlytics.log() is called immediately before Firebase.crashlytics.recordException() on a background thread, the breadcrumb does not appear in the Logs & Breadcrumbs section of the non-fatal report in the Firebase console. The exception itself is reported correctly — only the breadcrumb is missing.
Wrapping both calls in Handler(Looper.getMainLooper()).post {} resolves the issue and the breadcrumb appears as expected.
The Crashlytics SDK documentation makes no mention of a main-thread requirement for log(). There is no warning, error, or log output indicating that the call was ignored.

Steps to reproduce:

  1. Call Firebase.crashlytics.log("message") from a background thread
  2. Call Firebase.crashlytics.recordException(throwable) immediately after on the same thread
  3. Relaunch the app to flush the report
  4. Open the non-fatal event in the Firebase console → Logs & Breadcrumbs is empty
  • Expected: breadcrumb appears attached to the non-fatal report
  • Actual: breadcrumb is silently dropped
  • Workaround: wrap both calls in Handler(Looper.getMainLooper()).post {}

Relevant Code:

Broken — breadcrumb does not appear on the non-fatal report

// Called from a background thread (e.g. WorkManager coroutine)
private class CrashlyticsTree : Timber.Tree() {
    override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
        when (priority) {
            Log.VERBOSE, Log.DEBUG, Log.INFO -> Unit
            else -> {
                Firebase.crashlytics.log(message)           // ← breadcrumb missing from report
                t?.let { Firebase.crashlytics.recordException(it) }
            }
        }
    }
}

// Trigger (from a background thread):
Timber.w(Exception("Test ${System.currentTimeMillis()}"), "Hello Exception")

Fixed — wrapping in Handler(Looper.getMainLooper()).post {} attaches the breadcrumb correctly

private class CrashlyticsTree : Timber.Tree() {
    override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
        when (priority) {
            Log.VERBOSE, Log.DEBUG, Log.INFO -> Unit
            else -> {
                Handler(Looper.getMainLooper()).post {
                    Firebase.crashlytics.log(message)           // ← breadcrumb now appears
                    t?.let { Firebase.crashlytics.recordException(it) }
                }
            }
        }
    }
}

// Trigger (from a background thread):
Timber.w(Exception("Test ${System.currentTimeMillis()}"), "Hello Exception")

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions