stablyai/orca · warning · Error

Daemon temporarily unavailable; reconnect

Error message

Daemon temporarily unavailable; reconnect

What it means

routeRequest's createOrAttach branch first checks idleShutdownState; if it is anything other than 'running' (i.e. 'idle-shutdown-pending' or 'shutting-down'), the daemon refuses new session creation with a plain Error('Daemon temporarily unavailable; reconnect'). A retiring daemon will still drain/attach existing sessions but will not admit new ones.

Source

Thrown at src/main/daemon/daemon-server.ts:970

        this.historySeedTransfers.append(
          clientId,
          request.payload.transferId,
          request.payload.index,
          request.payload.data
        )
        return {}

      case 'finishHistorySeedTransfer':
        this.historySeedTransfers.finish(clientId, request.payload.transferId)
        return {}

      case 'abortHistorySeedTransfer':
        this.historySeedTransfers.abort(clientId, request.payload.transferId)
        return {}

      case 'createOrAttach': {
        if (this.idleShutdownState !== 'running') {
          throw new Error('Daemon temporarily unavailable; reconnect')
        }
        if (!client?.authenticatedPairEstablished || client.streamSocket === null) {
          // Why: a control-only replacement can't own terminal admission or erase the prior client's retirement request.
          throw new Error('Daemon client connection is incomplete; reconnect')
        }
        const p = request.payload
        const attachOnly = p.attachOnly === true
        // Why check here and not only on the watchdog: publishing cannot be made atomic against
        // a publisher preempted between proving an entry dead and replacing it, so this daemon
        // can lose the endpoint at any moment. The watchdog notices within a poll, which is far
        // too late if a session was accepted in between — that session is then reachable by
        // nobody, and the user sees a terminal that acknowledges input and never runs it.
        // Why creation only: an attach reaches a session this daemon already hosts, over a
        // connection that already exists. Refusing that would break the drain a retiring daemon
        // depends on, and it strands nothing — the session is already here.
        if (!attachOnly && this.hasLostEndpointOwnership()) {
          this.requestRetirementForLostEndpoint()
          throw new Error(DAEMON_ENDPOINT_LOST_MESSAGE)

View on GitHub (pinned to 1136503c6a)

Solutions

  1. On the client, reconnect (the launcher will fork/adopt a fresh daemon) and retry createOrAttach.
  2. Treat 'Daemon temporarily unavailable; reconnect' as transient — do not escalate to a fatal error in the UI.
  3. If reproducing frequently, review the idle-shutdown window and whether the client keeps the daemon pinned with intermittent activity.
Defensive patterns

Strategy: retry

Type guard

function isDaemonTemporarilyUnavailable(e: unknown): boolean {
  return e instanceof Error && e.message === 'Daemon temporarily unavailable; reconnect'
}

Try / catch

try {
  await daemon.createOrAttach(payload)
} catch (e) {
  if (isDaemonTemporarilyUnavailable(e)) {
    // reconnect (launcher forks/adopts a fresh daemon), then retry createOrAttach
  } else throw e
}

Prevention

When it happens

Trigger: Calling createOrAttach while the daemon is mid idle-shutdown (no fully-authenticated clients for the idle window), during a shutdown fence, or after retirement was requested due to endpoint loss.

Common situations: All windows closed, idle timer fired, daemon half-shut when the user reopens a terminal; endpoint ownership lost and the daemon is draining; an explicit shutdown RPC racing a new tab open.

Related errors


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