stablyai/orca · warning
Not connected: ${method}
Error message
Not connected: ${method} What it means
Thrown by sendRequest in rpc-client.ts (line 980-982) when the caller passed options.failWhenDisconnected:true AND the connection state is not 'connected' at call time. This is the fail-fast opt-in: by default sendRequest parks in waitForConnected and waits for a reconnect (replaying the request after), but interactive PTY writes (terminal bytes, composer sends) set failWhenDisconnected because a stale byte replayed after a 30s reconnect corrupts the terminal. The thrown method name identifies which RPC was refused.
Source
Thrown at mobile/src/transport/rpc-client.ts:981
registerPending: (id, onSettled) => pending.set(id, { resolve: onSettled, reject: onSettled }),
clearPending: (id) => pending.delete(id),
sendProbe: (id) => sendEncrypted({ id, deviceToken, method: 'status.get' }),
forceReconnect: closeAndSynthesize
})
openConnection()
return {
async sendRequest(
method: string,
params?: unknown,
options?: SendRequestOptions
): Promise<RpcResponse> {
const budget = openRpcRequestBudget(options)
const waitStart = budget.startedAt
const wasConnected = state === 'connected'
if (options?.failWhenDisconnected && !wasConnected) {
throw new Error(`Not connected: ${method}`)
}
await waitForConnected(options?.timeoutMs)
if (!wasConnected) {
console.log('[net] sendRequest waited for connect', {
method,
waitedMs: Date.now() - waitStart
})
}
return new Promise((resolve, reject) => {
const id = nextId()
const timeoutMs = resolvePostConnectRequestTimeout(budget, REQUEST_TIMEOUT_MS)
const timeout = setTimeout(() => {
pending.delete(id)
console.log('[net] sendRequest TIMEOUT', {
method,
timeoutMs,
stateView on GitHub (pinned to 1136503c6a)
Solutions
- If the call is idempotent/non-interactive, remove failWhenDisconnected to let it wait for reconnect.
- If interactive, surface 'Reconnecting…' to the user and queue the input locally for re-send once onStateChange reports 'connected'.
- Check client.getState() before calling — if not 'connected', decide wait-vs-fail explicitly rather than relying on the option.
- Subscribe to client.onStateChange to gate interactive sends on the connected state.
Example fix
// before — interactive send fails fast on disconnect
await client.sendRequest('terminal.write', bytes, { failWhenDisconnected: true })
// after — gate on connection state, queue while disconnected
if (client.getState() !== 'connected') {
pendingWrites.push(bytes) // replayed on 'connected' state change
return
}
await client.sendRequest('terminal.write', bytes) Defensive patterns
Strategy: validation
Validate before calling
// Before sendRequest with failWhenDisconnected, check state
function canSendNow(client: RpcClient): boolean {
return client.getState() === 'connected'
}
// usage:
if (options.failWhenDisconnected && !canSendNow(client)) {
// queue or surface 'reconnecting' instead of letting sendRequest throw
pendingWrites.push({ method, params })
return
} Type guard
function isNotConnectedError(error: unknown): boolean {
return error instanceof Error && /^Not connected: /.test(error.message)
} Try / catch
try {
await client.sendRequest(method, params, { failWhenDisconnected: true })
} catch (error) {
if (isNotConnectedError(error)) {
pendingWrites.push({ method, params })
client.onStateChange(function listener(state) {
if (state === 'connected') {
client.onStateChange.removeListener?.(listener)
void flushPending()
}
})
return
}
throw error
} Prevention
- Subscribe to client.onStateChange and gate interactive sends on state === 'connected'.
- Only set failWhenDisconnected for calls whose semantics break under delayed replay (terminal writes, composer sends).
- Queue interactive input locally while disconnected and replay on reconnect.
When it happens
Trigger: client.sendRequest(method, params, { failWhenDisconnected: true }) called while state ∈ {'connecting','handshaking','disconnected','reconnecting','auth-failed'}. Most commonly: terminal write paths, composer 'send' loops, or any caller that sized its semantics against immediate delivery rather than eventual delivery.
Common situations: Connection dropped mid-session (network blip, app backgrounded, desktop asleep) and the terminal/composer attempted to write. Without failWhenDisconnected these would hang on waitForConnected (up to options.timeoutMs or the GIVE_UP_AFTER_ATTEMPTS cap) and then replay — for interactive input that's worse than failing fast.
Related errors
- Waiting for desktop...
- Failed to send notes
- Failed to create terminal
- Created terminal response was invalid
- Failed to create terminal
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/220f9b38c7bf0c52.
Report an issue: GitHub.