{"record":{"id":"005ed846b7026554","repo":"stablyai/orca","slug":"daemon-temporarily-unavailable-reconnect","errorCode":null,"errorMessage":"Daemon temporarily unavailable; reconnect","messagePattern":"Daemon temporarily unavailable; reconnect","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/main/daemon/daemon-server.ts","lineNumber":970,"sourceCode":"        this.historySeedTransfers.append(\n          clientId,\n          request.payload.transferId,\n          request.payload.index,\n          request.payload.data\n        )\n        return {}\n\n      case 'finishHistorySeedTransfer':\n        this.historySeedTransfers.finish(clientId, request.payload.transferId)\n        return {}\n\n      case 'abortHistorySeedTransfer':\n        this.historySeedTransfers.abort(clientId, request.payload.transferId)\n        return {}\n\n      case 'createOrAttach': {\n        if (this.idleShutdownState !== 'running') {\n          throw new Error('Daemon temporarily unavailable; reconnect')\n        }\n        if (!client?.authenticatedPairEstablished || client.streamSocket === null) {\n          // Why: a control-only replacement can't own terminal admission or erase the prior client's retirement request.\n          throw new Error('Daemon client connection is incomplete; reconnect')\n        }\n        const p = request.payload\n        const attachOnly = p.attachOnly === true\n        // Why check here and not only on the watchdog: publishing cannot be made atomic against\n        // a publisher preempted between proving an entry dead and replacing it, so this daemon\n        // can lose the endpoint at any moment. The watchdog notices within a poll, which is far\n        // too late if a session was accepted in between — that session is then reachable by\n        // nobody, and the user sees a terminal that acknowledges input and never runs it.\n        // Why creation only: an attach reaches a session this daemon already hosts, over a\n        // connection that already exists. Refusing that would break the drain a retiring daemon\n        // depends on, and it strands nothing — the session is already here.\n        if (!attachOnly && this.hasLostEndpointOwnership()) {\n          this.requestRetirementForLostEndpoint()\n          throw new Error(DAEMON_ENDPOINT_LOST_MESSAGE)","sourceCodeStart":952,"sourceCodeEnd":988,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/daemon/daemon-server.ts#L952-L988","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["On the client, reconnect (the launcher will fork/adopt a fresh daemon) and retry createOrAttach.","Treat 'Daemon temporarily unavailable; reconnect' as transient — do not escalate to a fatal error in the UI.","If reproducing frequently, review the idle-shutdown window and whether the client keeps the daemon pinned with intermittent activity."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"function isDaemonTemporarilyUnavailable(e: unknown): boolean {\n  return e instanceof Error && e.message === 'Daemon temporarily unavailable; reconnect'\n}","tryCatchPattern":"try {\n  await daemon.createOrAttach(payload)\n} catch (e) {\n  if (isDaemonTemporarilyUnavailable(e)) {\n    // reconnect (launcher forks/adopts a fresh daemon), then retry createOrAttach\n  } else throw e\n}","preventionTips":["Treat this as transient in the UI — reconnect and retry rather than surfacing a fatal.","Review the idle-shutdown window if the daemon retires too eagerly under your usage.","Avoid racing createOrAttach against an explicit shutdown RPC."],"tags":["daemon","idle-shutdown","create-or-attach","reconnect","transient"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}