stablyai/orca · error · Error

terminal_pane_owner_unverified

Error message

terminal_pane_owner_unverified

What it means

Thrown at pty.ts:854-855 when provider.spawn() during attachStablePaneOwner rejects with TerminalSessionOwnerUnverifiedError. That error (daemon-errors.ts:24) is raised by the daemon's session router (daemon-session-owner-resolution.ts:99,116) when a session's owner cannot be verified: the resolution kind is 'unknown' (session id not recognized across providers), or a SessionNotFoundError occurred with multiple providers and the router cannot prove which provider owns the session. It signals 'cannot prove this pane belongs to the claimed owner' — a safety refusal, not a crash.

Source

Thrown at src/main/ipc/pty.ts:855

    result = await provider.spawn({
      ...spawnOptions,
      sessionId: owner.ptyId,
      attachOnly: true,
      expectedIncarnationId: owner.runtimeIncarnationId ?? owner.persistedIncarnationId,
      expectedIncarnationIsAuthoritative: owner.runtimeIncarnationId !== undefined,
      isNewSession: undefined,
      command: undefined,
      commandDelivery: undefined,
      startupCommandDelivery: undefined,
      launchAgent: undefined,
      startupIngress: undefined,
      agentSessionEnsure: undefined,
      agentSessionCreateOperationId: undefined,
      onPtySpawnCommitted: undefined
    })
  } catch (error) {
    if (error instanceof TerminalSessionOwnerUnverifiedError) {
      throw new Error('terminal_pane_owner_unverified')
    }
    // Why: translate before paired-runtime RPC strips the socket error's code and syscall.
    if (isDaemonEndpointGoneError(error)) {
      throw new TerminalHostGoneError()
    }
    if (!isPtyAlreadyGoneError(error)) {
      throw error
    }
    const ownerBeforeRetire = args.resolveOwner?.()
    if (
      ownerBeforeRetire &&
      (ownerBeforeRetire.ptyId !== owner.ptyId ||
        ownerBeforeRetire.runtimeIncarnationId !== owner.runtimeIncarnationId ||
        ownerBeforeRetire.hasPersistedBinding !== owner.hasPersistedBinding ||
        ownerBeforeRetire.persistedIncarnationId !== owner.persistedIncarnationId)
    ) {
      throw new Error('terminal_pane_owner_changed')
    }

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Treat this as 'pane cannot be reattached' — create a fresh terminal session instead of retrying the attach.
  2. If the daemon was expected to know the session, confirm the daemon is the same instance (check daemon endpoint ownership / incarnation) — a restarted daemon legitimately does not recognize old sessions.
  3. Verify the ptyId/incarnationId passed to spawn match a session the daemon created.
  4. Do not loop/retry the attach: the comment at pty.ts:857 notes the daemon endpoint may be gone, which is a separate TerminalHostGoneError path.
Defensive patterns

Strategy: fallback

Type guard

function isTerminalPaneOwnerUnverified(e: unknown): boolean {
  return e instanceof Error && e.message === 'terminal_pane_owner_unverified'
}

Try / catch

try {
  await attachStablePaneOwner(ctx)
} catch (e) {
  if (e instanceof Error && e.message === 'terminal_pane_owner_unverified') {
    // pane cannot be reattached — create a fresh session instead of retrying
    await spawnFreshPty(ctx)
  } else throw e
}

Prevention

When it happens

Trigger: Reattaching to a stable terminal pane (attachOnly spawn) whose sessionId/incarnation the daemon cannot resolve to a known owner: the session was never created on this daemon, the incarnation id changed (daemon restarted and lost the session), or multiple providers are configured and ownership is ambiguous after a SessionNotFoundError.

Common situations: Daemon restarted (lost in-memory session registry) while the renderer still holds a stable-pane binding; a race between a pane retiring and a reattach attempt; remote/SSH daemon where the session id was never published to this daemon; incarnation mismatch after a host handover.

Related errors


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