stablyai/orca · warning · Error

Daemon client connection is incomplete; reconnect

Error message

Daemon client connection is incomplete; reconnect

What it means

In routeRequest, startHistorySeedTransfer (and createOrAttach, and others) require the client to have both authenticatedPairEstablished and a non-null streamSocket. A control-only replacement connection — one that authenticated the control channel but has not paired a data stream — cannot own terminal admission or history seeds, so the daemon throws a plain Error('Daemon client connection is incomplete; reconnect').

Source

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

  }

  private cancelPendingPtySpawnPreparationsForClient(clientId: string): void {
    for (const pending of this.pendingPtySpawnPreparations.values()) {
      for (const preparation of pending) {
        if (preparation.clientId === clientId) {
          preparation.canceled = true
        }
      }
    }
  }

  private async routeRequest(clientId: string, request: DaemonRequest): Promise<unknown> {
    const client = this.clients.get(clientId)

    switch (request.type) {
      case 'startHistorySeedTransfer': {
        if (!client?.authenticatedPairEstablished || client.streamSocket === null) {
          throw new Error('Daemon client connection is incomplete; reconnect')
        }
        const transferId = this.historySeedTransfers.start(clientId, request.payload)
        return { transferId }
      }

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

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

View on GitHub (pinned to 1136503c6a)

Solutions

  1. On the client, await the full pairing (control + stream) before issuing startHistorySeedTransfer or createOrAttach.
  2. Treat the message as a soft signal to reconnect: tear down and re-establish both channels, then retry.
  3. Audit the client connection handshake to confirm authenticatedPairEstablished only flips after the stream socket is set.
Defensive patterns

Strategy: retry

Type guard

function isIncompleteClientConnection(e: unknown): boolean {
  return e instanceof Error && e.message === 'Daemon client connection is incomplete; reconnect'
}

Try / catch

try {
  await daemon.createOrAttach(payload)
} catch (e) {
  if (isIncompleteClientConnection(e)) {
    // tear down both channels, re-establish control + stream pairing, then retry
  } else throw e
}

Prevention

When it happens

Trigger: Client sent the RPC before establishing the stream channel pairing; the stream socket disconnected and a replacement control connection took over but the new stream pair is still pending; a buggy client that tries history-seed transfer or createOrAttach before hello/pair completes.

Common situations: Reconnect races where control re-establishes faster than stream; a client downgrade that skips the pairing step; transient stream drop mid-session with the renderer retrying immediately.

Related errors


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