Tencent/matrix · error · IllegalStateException
token with pid=$pid not found
Error message
token with pid=$pid not found
What it means
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.
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.
Example fix
// before
val token = removeToken(pid)
// after
val token = try {
removeToken(pid)
} catch (e: IllegalStateException) {
MatrixLog.w(TAG, "token already removed for pid=$pid")
null
} Defensive patterns
Strategy: fallback
Validate before calling
val existing = supervisor.knownPids[pid] if (existing != null) removeToken(pid)
Try / catch
val token = try {
removeToken(pid)
} catch (e: IllegalStateException) {
null // already removed or never registered — treat as no-op
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- token with name=$name not found
- call forbidden
- NOT allow for subordinate processes
- Supervisor NOT initialized yet or Supervisor is disabled!!!
- backgroundLruKill should only be called in supervisor
AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08).
Data as JSON: /api/errors/19e98e47c604d9c2.
Report an issue: GitHub.
Appendix: source
Thrown at matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/lifecycle/supervisor/SupervisorService.kt:326
by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { ConcurrentHashMap() }
private val nameToToken: ConcurrentHashMap<String, ProcessToken>
by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { ConcurrentHashMap() }
fun addToken(token: ProcessToken) {
pidToToken[token.pid] = token
nameToToken[token.name] = token
}
fun getToken(pid: Int) = pidToToken[pid]
fun getToken(name: String) = nameToToken[name]
fun removeToken(pid: Int): ProcessToken {
val rm = pidToToken.remove(pid)
rm?.let {
nameToToken.remove(rm.name)
return rm
}
throw IllegalStateException("token with pid=$pid not found")
}
fun isEmpty(): Boolean =
pidToToken.isEmpty() || pidToToken.all { it.key == Process.myPid() }
fun removeToken(name: String): ProcessToken {
val rm = nameToToken.remove(name)
rm?.let {
pidToToken.remove(rm.pid)
return rm
}
throw IllegalStateException("token with name=$name not found")
}
}
private class RemoteProcessLifecycleProxy(val token: ProcessToken) : StatefulOwner() {
init {View on GitHub (pinned to 3b8293bd65)