{"record":{"id":"15794a49060b4cf2","repo":"Tencent/matrix","slug":"call-forbidden","errorCode":null,"errorMessage":"call forbidden","messagePattern":"call forbidden","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/lifecycle/supervisor/DispatcherStateOwner.kt","lineNumber":46,"sourceCode":"        fun ownersToProcessTokens(context: Context) =\n            dispatchOwners.values\n                .map { ProcessToken.current(context, it.name, it.attachedSource.active()) }\n                .toTypedArray()\n\n        fun dispatchOn(name: String) {\n            dispatchOwners[name]?.dispatchOn()\n        }\n\n        fun dispatchOff(name: String) {\n            dispatchOwners[name]?.dispatchOff()\n        }\n\n        /**\n         * call from supervisor\n         */\n        fun syncStates(supervisorToken: ProcessToken, scene: String) {\n            if (!ProcessSupervisor.isSupervisor) {\n                throw IllegalStateException(\"call forbidden\")\n            }\n            dispatchOwners.forEach {\n                val active = it.value.active()\n                MatrixLog.i(ProcessSupervisor.tag, \"syncStates: ${it.key} $active\")\n                ProcessSubordinate.manager.dispatchState(supervisorToken, scene, it.key, active)\n            }\n        }\n\n        fun attach(application: Application) {\n            dispatchOwners.forEach {\n                it.value.apply {\n                    attachedObserver?.let { o -> attachedSource.removeObserver(o) } // prevent double-observe\n                    attachedObserver = object : IStateObserver, ISerialObserver {\n                        override fun on() {\n                            MatrixLog.d(ProcessSupervisor.tag, \"attached ${it.key} turned ON\")\n                            safeApply(\"${ProcessSupervisor.tag}.${it.key}\") {\n                                ProcessSupervisor.supervisorProxy?.onStateChanged(\n                                    ProcessToken.current(application, it.key, true)","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/lifecycle/supervisor/DispatcherStateOwner.kt#L28-L64","documentation":"DispatcherStateOwner.syncStates() is an internal API meant to be invoked only by the ProcessSupervisor to push owner states to subordinate processes. It throws IllegalStateException(\"call forbidden\") when called from any process that is not the supervisor, to prevent app code from corrupting supervisor-driven state synchronization.","triggerScenarios":"Application code (or a subordinate process) calling DispatcherStateOwner.syncStates(token, scene) directly; accidentally linking or invoking the supervisor-only static method from non-supervisor code paths.","commonSituations":"Trying to force a state sync after seeing stale owner states; copy-pasting supervisor-side code into a subordinate process; custom dispatch logic that bypasses ProcessSupervisor.","solutions":["Do not call syncStates from app code; it is supervisor-internal. Use the public owner APIs or let the supervisor drive synchronization.","Guard the call site with `if (ProcessSupervisor.isSupervisor)` before invoking.","If subordinate processes need updated state, trigger it via the supervisor (e.g. scene dispatch from the supervisor side).","Catch IllegalStateException as a safety net when probing process roles at runtime."],"exampleFix":"// before\nDispatcherStateOwner.syncStates(token, scene)\n// after\nif (ProcessSupervisor.isSupervisor) {\n    DispatcherStateOwner.syncStates(token, scene)\n}","handlingStrategy":"validation","validationCode":"if (!ProcessSupervisor.isSupervisor) {\n    MatrixLog.w(TAG, \"syncStates is supervisor-only, skipping\")\n    return\n}\nDispatcherStateOwner.syncStates(token, scene)","typeGuard":"fun canSyncStates(): Boolean =\n    runCatching { ProcessSupervisor.isSupervisor }.getOrDefault(false)","tryCatchPattern":"try {\n    DispatcherStateOwner.syncStates(token, scene)\n} catch (e: IllegalStateException) {\n    MatrixLog.w(TAG, \"syncStates called outside supervisor\", e)\n}","preventionTips":["Treat syncStates as internal API; never call it from app code.","Guard every supervisor API call with ProcessSupervisor.isSupervisor.","Document process-role invariants at call sites that mix supervisor/subordinate logic."],"tags":["android","process-supervisor","api-misuse","illegal-state"],"backgroundTag":"insufficient-permissions","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"}