stablyai/orca · error · TerminalSessionOwnerUnverifiedError

Terminal session owner could not be verified: ${sessionId}

Error message

Terminal session owner could not be verified: ${sessionId}

What it means

TerminalSessionOwnerUnverifiedError: during attach-only spawn, resolve() returned kind 'unknown', meaning the daemon could not determine which provider owns the session. This is distinct from 'absent' (the session provably does not exist) — 'unknown' means the inventory was incomplete or the epoch changed mid-resolution (a provider was invalidated concurrently), so ownership is un-verifiable rather than definitely missing.

Source

Thrown at src/main/daemon/daemon-session-owner-resolution.ts:99

        }
        if (this.providers.length === 1) {
          throw error
        }
        if (routed && this.routes.get(opts.sessionId) === routed) {
          this.forgetRoute(opts.sessionId, routed)
        }
      }
    }

    assertClientConnected(opts.signal)
    const resolution = await this.resolve(
      opts.sessionId,
      opts.expectedIncarnationId,
      opts.expectedIncarnationIsAuthoritative
    )
    assertClientConnected(opts.signal)
    if (resolution.kind === 'unknown') {
      throw new TerminalSessionOwnerUnverifiedError(opts.sessionId)
    }
    if (resolution.kind === 'absent') {
      throw new SessionNotFoundError(opts.sessionId)
    }
    try {
      const result = await resolution.provider.spawn(opts)
      if (
        !result.exitedBeforeSpawnReply &&
        result.id === opts.sessionId &&
        result.isReattach === true
      ) {
        this.recordRoute(result.id, resolution.provider, result.incarnationId)
      }
      return result
    } catch (error) {
      if (error instanceof SessionNotFoundError && this.providers.length > 1) {
        throw new TerminalSessionOwnerUnverifiedError(opts.sessionId)
      }

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Retry spawnAttachOnly after a short backoff — the epoch change or provider cooldown (1s) is transient and a fresh inventory may resolve cleanly.
  2. Ensure all expected providers are healthy before issuing attach; if a provider is permanently gone, remove it so inventory can complete.
  3. If retries keep returning unknown, fall back to creating a fresh session rather than looping on an un-resolvable attach.
  4. Check that invalidateProvider is not being called spuriously during steady-state attaches.
Defensive patterns

Strategy: retry

Type guard

import { TerminalSessionOwnerUnverifiedError } from './daemon-errors'
function isOwnerUnverified(e: unknown): boolean {
  return e instanceof TerminalSessionOwnerUnverifiedError
}

Try / catch

for (let attempt = 0; attempt < 3; attempt++) {
  try {
    return await resolver.spawnAttachOnly(opts)
  } catch (e) {
    if (e instanceof TerminalSessionOwnerUnverifiedError && attempt < 2) {
      await delay(100 * (attempt + 1))  // let epoch/cooldown settle
      continue
    }
    throw e
  }
}

Prevention

When it happens

Trigger: spawnAttachOnly where the provider inventory was incomplete (a provider failed to report) or the epoch changed during resolution because invalidateProvider() ran (e.g., a daemon adapter disconnected between inventory and resolution), leaving no authoritative answer.

Common situations: Multiple PTY providers registered and one becomes unreachable during attach; a daemon handover invalidating routes mid-call; concurrent session teardown racing an attach on a multi-provider host (WSL + native, or daemon + fallback).

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/5428925a9e3e6f31. Report an issue: GitHub.