{"record":{"id":"19e98e47c604d9c2","repo":"Tencent/matrix","slug":"token-with-pid-pid-not-found","errorCode":null,"errorMessage":"token with pid=$pid not found","messagePattern":"token with pid=\\$pid not found","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/lifecycle/supervisor/SupervisorService.kt","lineNumber":326,"sourceCode":"                by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { ConcurrentHashMap() }\n        private val nameToToken: ConcurrentHashMap<String, ProcessToken>\n                by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { ConcurrentHashMap() }\n\n        fun addToken(token: ProcessToken) {\n            pidToToken[token.pid] = token\n            nameToToken[token.name] = token\n        }\n\n        fun getToken(pid: Int) = pidToToken[pid]\n        fun getToken(name: String) = nameToToken[name]\n\n        fun removeToken(pid: Int): ProcessToken {\n            val rm = pidToToken.remove(pid)\n            rm?.let {\n                nameToToken.remove(rm.name)\n                return rm\n            }\n            throw IllegalStateException(\"token with pid=$pid not found\")\n        }\n\n        fun isEmpty(): Boolean =\n            pidToToken.isEmpty() || pidToToken.all { it.key == Process.myPid() }\n\n        fun removeToken(name: String): ProcessToken {\n            val rm = nameToToken.remove(name)\n            rm?.let {\n                pidToToken.remove(rm.pid)\n                return rm\n            }\n            throw IllegalStateException(\"token with name=$name not found\")\n        }\n    }\n\n    private class RemoteProcessLifecycleProxy(val token: ProcessToken) : StatefulOwner() {\n\n        init {","sourceCodeStart":308,"sourceCodeEnd":344,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/lifecycle/supervisor/SupervisorService.kt#L308-L344","documentation":"SupervisorService tracks subordinate processes in pidToToken/nameToToken maps. removeToken(pid) throws IllegalStateException(\"token with pid=$pid not found\") when no ProcessToken is registered for the given pid, i.e. the process died or was never registered as a subordinate.","triggerScenarios":"Calling removeToken(pid) for a pid that never connected to the supervisor, was already removed by a prior call, or whose binding died and was cleaned up by another code path (e.g. onServiceDisconnected).","commonSituations":"Handling binder-death callbacks where two listeners both try to remove the token; stale pid from a cached process record; race between process death handling and manual cleanup.","solutions":["Check existence before removing (e.g. track known pids or catch IllegalStateException) and treat missing tokens as no-ops.","Centralize token removal in one callback (binder death OR explicit removal) to avoid double removal.","Refresh the pid from the live binding before calling removeToken.","Use the returned ProcessToken flow idempotently: ignore \"not found\" as an expected race outcome."],"exampleFix":"// before\nval token = removeToken(pid)\n// after\nval token = try {\n    removeToken(pid)\n} catch (e: IllegalStateException) {\n    MatrixLog.w(TAG, \"token already removed for pid=$pid\")\n    null\n}","handlingStrategy":"fallback","validationCode":"val existing = supervisor.knownPids[pid]\nif (existing != null) removeToken(pid)","typeGuard":null,"tryCatchPattern":"val token = try {\n    removeToken(pid)\n} catch (e: IllegalStateException) {\n    null // already removed or never registered — treat as no-op\n}","preventionTips":["Make token removal idempotent: catch \"not found\" and continue.","Use a single cleanup path (binder death) to avoid double removal.","Track live pids in the caller so removeToken is only called for registered entries."],"tags":["android","process-supervisor","bookkeeping","state-race"],"backgroundTag":"record-not-found","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"}