{"record":{"id":"e33e05b436d79b3d","repo":"Tencent/matrix","slug":"not-allow-to-add-multisourcestatefulowner-as-sourc","errorCode":null,"errorMessage":"NOT allow to add MultiSourceStatefulOwner as source, consider to add its shadow owner","messagePattern":"NOT allow to add MultiSourceStatefulOwner as source, consider to add its shadow owner","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/lifecycle/StatefulOwner.kt","lineNumber":296,"sourceCode":" * @since 2021/9/24\n */\nopen class MultiSourceStatefulOwner(\n    private val reduceOperator: (statefuls: Collection<IStateful>) -> Boolean,\n    vararg statefulOwners: IStatefulOwner,\n) : StatefulOwner(true), IStateObserver, IMultiSourceOwner {\n\n    private val sourceOwners = ConcurrentLinkedQueue<IStatefulOwner>()\n\n    init {\n        statefulOwners.forEach {\n            register(it)\n        }\n    }\n\n    private fun register(owner: IStatefulOwner) {\n        owner.let {\n            if (it is MultiSourceStatefulOwner) {\n                throw IllegalArgumentException(\"NOT allow to add MultiSourceStatefulOwner as source, consider to add its shadow owner\")\n            }\n            sourceOwners.add(it)\n            it.observeForever(this)\n        }\n    }\n\n    private fun unregister(owner: StatefulOwner) {\n        owner.also {\n            sourceOwners.remove(it)\n            it.removeObserver(this)\n            onStateChanged()\n        }\n    }\n\n    override fun addSourceOwner(owner: StatefulOwner) = register(owner)\n\n    open fun addSourceOwner(owner: LifecycleOwner): StatefulOwner =\n        owner.toStateOwner().also { addSourceOwner(it) }","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/lifecycle/StatefulOwner.kt#L278-L314","documentation":"MultiSourceStatefulOwner aggregates several source owners via a private shadow owner. Nesting a MultiSourceStatefulOwner directly as a source of another owner is unsupported, so register() throws IllegalArgumentException and directs the caller to add its shadow owner instead.","triggerScenarios":"Calling addSourceOwner(multiSourceOwner) where multiSourceOwner is a MultiSourceStatefulOwner instance; the private register() detects the type and throws.","commonSituations":"Building chains of combined/derived lifecycle owners and passing an already-composed owner as a source; misunderstanding that MultiSourceStatefulOwner exposes a shadow owner for composition.","solutions":["Pass multiSourceOwner.shadowOwner instead of the MultiSourceStatefulOwner itself to addSourceOwner.","Flatten the composition: add the individual underlying owners as sources directly.","Refactor so composed owners are not fed into other StatefulOwners."],"exampleFix":"// before\nowner.addSourceOwner(multiSourceOwner) // throws\n// after\nowner.addSourceOwner(multiSourceOwner.shadowOwner)","handlingStrategy":"type-guard","validationCode":"fun safeAddSource(owner: IStatefulOwner, source: IStatefulOwner) {\n    val src = (source as? MultiSourceStatefulOwner)?.shadowOwner ?: source\n    owner.addSourceOwner(src)\n}","typeGuard":"fun isComposableSource(s: IStatefulOwner): Boolean = s !is MultiSourceStatefulOwner","tryCatchPattern":"try {\n    owner.addSourceOwner(source)\n} catch (e: IllegalArgumentException) {\n    MatrixLog.w(TAG, \"use shadowOwner for MultiSourceStatefulOwner\", e)\n}","preventionTips":["Always pass .shadowOwner when a source may be a MultiSourceStatefulOwner.","Centralize source-owner wiring in one helper that normalizes the type.","Avoid nesting composed owners; add primitive owners as sources."],"tags":["android","lifecycle","illegal-argument","composition"],"backgroundTag":"unsupported-operation","analyzedSha":"3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7","analyzedAt":"2026-09-08T08:01:39.722Z","contentChangedAt":"2026-09-08T08:01:39.722Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}