Tencent/matrix · error · IllegalStateException

NOT allow to observe with DESTROYED lifecycle owner

Error message

NOT allow to observe with DESTROYED lifecycle owner

What it means

Matrix's AutoReleaseObserverWrapper attaches an IStateObserver to a LifecycleOwner's lifecycle. In its init block it checks whether the lifecycle owner's currentState is DESTROYED; observing a destroyed owner is meaningless because the observer would never receive events and the attachment contract forbids it, so it throws IllegalStateException immediately.

Solutions

  1. Check lifecycleOwner.lifecycle.currentState != Lifecycle.State.DESTROYED before registering the observer.
  2. Register the observer earlier in the owner's lifecycle (e.g. onCreate/onStart) instead of in late or async callbacks.
  3. Skip registration when the owner is destroyed instead of observing, e.g. wrap the observe call in a state check.

Example fix

// before
owner.observeForever(lifecycleOwner, myObserver)
// after
if (lifecycleOwner.lifecycle.currentState != Lifecycle.State.DESTROYED) {
    owner.observeForever(lifecycleOwner, myObserver)
}
Defensive patterns

Strategy: validation

Validate before calling

fun canObserve(owner: LifecycleOwner) = owner.lifecycle.currentState != Lifecycle.State.DESTROYED

Type guard

fun LifecycleOwner.isAliveForObserving() = lifecycle.currentState.isAtLeast(Lifecycle.State.INITIALIZED) && lifecycle.currentState != Lifecycle.State.DESTROYED

Try / catch

try {
    owner.observeForever(lifecycleOwner, observer)
} catch (e: IllegalStateException) {
    MatrixLog.w(TAG, "owner already destroyed, skip observe", e)
}

Prevention

When it happens

Trigger: Calling IStatefulOwner.observeForever / observe (or any API that wraps the observer in AutoReleaseObserverWrapper) with a LifecycleOwner whose lifecycle.getCurrentState() == Lifecycle.State.DESTROYED, e.g. an Activity or Fragment already destroyed.

Common situations: Registering a Matrix observer in a callback that fires after the Activity/Fragment is destroyed (async result delivery, onDestroy cleanup paths, work finishing after configuration change), or caching a LifecycleOwner reference and using it after teardown.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08). Data as JSON: /api/errors/898c6c7dd3a9c10e. Report an issue: GitHub.

Appendix: source

Thrown at matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/lifecycle/StatefulOwner.kt:99

interface IMultiSourceOwner {
    fun addSourceOwner(owner: StatefulOwner)
    fun removeSourceOwner(owner: StatefulOwner)
}

private open class ObserverWrapper(val observer: IStateObserver, val statefulOwner: StatefulOwner) {
    open fun isAttachedTo(owner: LifecycleOwner?) = false
}

private class AutoReleaseObserverWrapper constructor(
    val lifecycleOwner: LifecycleOwner,
    targetObservable: StatefulOwner,
    observer: IStateObserver
) : ObserverWrapper(observer, targetObservable), LifecycleObserver {

    init {
        if (lifecycleOwner.lifecycle.currentState == Lifecycle.State.DESTROYED) {
            throw IllegalStateException("NOT allow to observe with DESTROYED lifecycle owner")
        }
        lifecycleOwner.lifecycle.addObserver(this)
    }

    override fun isAttachedTo(owner: LifecycleOwner?) = lifecycleOwner == owner

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun release() {
        statefulOwner.removeObserver(observer)
    }
}

private fun ObserverWrapper.checkLifecycle(lifecycleOwner: LifecycleOwner?): Boolean {
    val broken = if (lifecycleOwner != null) {
        isAttachedTo(lifecycleOwner)
    } else {
        this is AutoReleaseObserverWrapper
    }

View on GitHub (pinned to 3b8293bd65)