stablyai/orca · error
Session "${opts.sessionId}" is terminating
Error message
Session "${opts.sessionId}" is terminating What it means
A distinct, more specific error than SessionNotFoundError: the session exists, is alive, and is marked isTerminating (e.g., it was SIGKILLed but the child has not yet been reaped). Recreating it now could hide two live generations behind the same public session id. Throwing a unique message lets callers distinguish 'in a terminal exit race' from 'genuinely gone'.
Source
Thrown at src/main/daemon/terminal-host-session-create.ts:60
if (existing && existing.isAlive && !existing.isTerminating) {
const snapshot = existing.getSnapshot()
existing.detachAllClients()
const token = existing.attachClient(opts.streamClient)
return {
isNew: false,
snapshot,
pid: existing.pid,
shellState: existing.shellState,
incarnationId: existing.incarnationId,
...getDaemonSessionResultMetadata(existing),
attachToken: token
}
}
if (existing?.isAlive && existing.isTerminating) {
// Why: replacing a SIGKILLed-but-unreaped child could hide two live
// generations behind the same public session id.
throw new Error(`Session "${opts.sessionId}" is terminating`)
}
if (opts.attachOnly) {
// Why: an adopted claim proves only one owner generation; it must never
// turn an exit race into permission to spawn an unclaimed shell.
throw new SessionNotFoundError(opts.sessionId)
}
if (existing) {
existing.dispose()
deps.sessions.delete(opts.sessionId)
deps.onDeadSessionRemoved(opts.sessionId)
}
deps.killedTombstones.clearForCreate(opts.sessionId)
const size = normalizePtySize(opts.cols, opts.rows)
const wslDistro = resolveWslSessionContext(opts)?.distro
const subprocess = deps.spawnSubprocess({
sessionId: opts.sessionId,View on GitHub (pinned to 1136503c6a)
Solutions
- Wait for the session's exit to be fully reaped (the exit handler runs) before recreating under the same id.
- If you must proceed immediately, create under a new sessionId rather than reusing the terminating one.
- Track isTerminating state client-side and avoid reusing ids that are mid-exit.
- Ensure the kill->reap->recreate sequence is serialized, not concurrent.
Defensive patterns
Strategy: retry
Type guard
function isSessionTerminating(e: unknown, sessionId: string): boolean {
return e instanceof Error && e.message === `Session "${sessionId}" is terminating`
} Try / catch
try {
return await createOrAttachTerminalSession(opts, deps)
} catch (e) {
if (e instanceof Error && e.message === `Session "${opts.sessionId}" is terminating`) {
await waitForSessionReaped(opts.sessionId) // exit handler runs
return await createOrAttachTerminalSession(opts, deps)
}
throw e
} Prevention
- Wait for the killed session to be fully reaped before recreating under the same id.
- If immediate creation is required, use a new sessionId instead of reusing the terminating one.
- Serialize the kill->reap->recreate sequence; do not overlap SIGKILL with a fresh create.
When it happens
Trigger: createOrAttachTerminalSession where existing?.isAlive && existing.isTerminating, reached after the live-attach branch and not via the sessionTeardown map. The process was killed but reaping/descendant-capture is incomplete.
Common situations: Recreating a session immediately after sending SIGKILL but before the exit handler reaped the process; a createOrAttach racing the reap window of a killed shell; rapid kill+reopen sequences.
Related errors
- Session not found: ${sessionId}
- Wayland GPU sandbox validation requires a Wayland session.
- relay pairing client closed
- mobile pairing cancelled
- Linux computer use requires an active desktop session; missi
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/7ff710fd79103124.
Report an issue: GitHub.