Tencent/matrix · error · IllegalStateException

backgroundLruKill should only be called in supervisor

Error message

backgroundLruKill should only be called in supervisor

What it means

SupervisorService.backgroundLruKill() performs LRU-based killing of background processes and is restricted to the supervisor process. It throws IllegalStateException when called while ProcessSupervisor.isSupervisor is false, preventing non-supervisor processes from triggering process kills.

Solutions

  1. Guard the call with `if (ProcessSupervisor.isSupervisor)` before invoking backgroundLruKill.
  2. Move LRU-kill invocations into supervisor-only code (e.g. inside the SupervisorService).
  3. Verify ProcessSupervisor.init ran and enable flags make this process the supervisor.
  4. Skip the operation gracefully (log and return) in non-supervisor processes instead of calling.

Example fix

// before
SupervisorService.backgroundLruKill(killedCallback)
// after
if (ProcessSupervisor.isSupervisor) {
    SupervisorService.backgroundLruKill(killedCallback)
}
Defensive patterns

Strategy: validation

Validate before calling

if (ProcessSupervisor.isSupervisor) {
    SupervisorService.backgroundLruKill(killedCallback)
} else {
    MatrixLog.w(TAG, "backgroundLruKill skipped: not supervisor")
}

Type guard

fun canBackgroundLruKill(): Boolean =
    runCatching { ProcessSupervisor.isSupervisor }.getOrDefault(false)

Try / catch

try {
    SupervisorService.backgroundLruKill(killedCallback)
} catch (e: IllegalStateException) {
    MatrixLog.w(TAG, "lru kill forbidden outside supervisor", e)
}

Prevention

When it happens

Trigger: Calling backgroundLruKill(...) from a subordinate process, or before ProcessSupervisor.init has determined the role (which also surfaces init errors); any call path where the supervisor role check fails.

Common situations: Memory-pressure callbacks that run in every process but invoke backgroundLruKill unconditionally; testing on a device where the supervisor service was not the calling process; disabled supervisor config causing role detection to differ from expectation.

Understand the failure class

Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.

Related errors


AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08). Data as JSON: /api/errors/511ec701c559e6bb. Report an issue: GitHub.

Appendix: source

Thrown at matrix/matrix-android/matrix-android-lib/src/main/java/com/tencent/matrix/lifecycle/supervisor/SupervisorService.kt:285

        MatrixLog.d(TAG, "onBind")
        return binder
    }

    override fun onDestroy() {
        super.onDestroy()
        MatrixLog.e(TAG, "SupervisorService destroyed!!!")
        instance = null
    }

    internal fun backgroundLruKill(
        killedCallback: (result: Int, process: String?, pid: Int) -> Unit
    ) {
        if (true != ProcessSupervisor.config?.enable) {
            MatrixLog.e(TAG, "supervisor was disabled")
            return
        }
        if (!isSupervisor) {
            throw IllegalStateException("backgroundLruKill should only be called in supervisor")
        }

        if (instance == null) {
            throw IllegalStateException("not initialized yet !")
        }

        targetKilledCallback = killedCallback
        val candidate = backgroundProcessLru.firstOrNull {
            it.name != MatrixUtil.getProcessName(this)
                    && !ProcessSupervisor.config!!.lruKillerWhiteList.contains(it.name)
        }

        if (candidate != null) {
//            DispatchReceiver.dispatchKill(this, candidate.name, candidate.pid)
            ProcessSubordinate.manager.dispatchKill(recentScene, candidate.name, candidate.pid)
        } else {
            killedCallback.invoke(LRU_KILL_NOT_FOUND, null, -1)
        }

View on GitHub (pinned to 3b8293bd65)