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
- Check lifecycleOwner.lifecycle.currentState != Lifecycle.State.DESTROYED before registering the observer.
- Register the observer earlier in the owner's lifecycle (e.g. onCreate/onStart) instead of in late or async callbacks.
- 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
- Always register lifecycle-observers in onCreate/onStart of the Activity/Fragment.
- Check currentState before any observe call on a cached LifecycleOwner.
- Avoid delivering async results into registration code after the owner may be destroyed.
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
- NOT initialized yet
- NOT initialized yet
- plugin start, but plugin has been already destroyed
- plugin start, but plugin has been already started
- plugin start, plugin listener is null
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)