stablyai/orca · error · Error

${commandLabel} ${args.join(' ')} ok=false: ${JSON.stringify

Error message

${commandLabel} ${args.join(' ')} ok=false: ${JSON.stringify(parsed)}

What it means

The CLI exited zero and produced parseable JSON, but the RPC envelope has ok === false — the application-level failure channel. The full parsed object is serialized into the message so the remote's error field/code is visible. This is the deepest of the three orcaJsonSync failure modes (104 spawn, 105 exit code, 106 RPC ok=false).

Source

Thrown at config/scripts/live-remote-freeze-rpc.mjs:101

    const started = performance.now()
    const result = spawnSync(cliInvocation.command, commandArgs(args, opts.local), {
      encoding: 'utf8',
      env: cliInvocation.env,
      maxBuffer: MAX_ORCA_RPC_OUTPUT_BYTES,
      timeout: opts.timeoutMs ?? 120_000
    })
    const elapsedMs = performance.now() - started
    if (result.error) {
      throw new Error(`${commandLabel} ${args.join(' ')} failed to start: ${String(result.error)}`)
    }
    if (result.status !== 0) {
      throw new Error(
        `${commandLabel} ${args.join(' ')} failed (${result.status}): ${result.stderr || result.stdout}`
      )
    }
    const parsed = JSON.parse(result.stdout)
    if (parsed.ok === false) {
      throw new Error(`${commandLabel} ${args.join(' ')} ok=false: ${JSON.stringify(parsed)}`)
    }
    return { parsed, elapsedMs, result: parsed.result }
  }

  function orcaJsonAsync(args, opts = {}) {
    const started = performance.now()
    return new Promise((resolve, reject) => {
      const child = spawn(cliInvocation.command, commandArgs(args, opts.local), {
        env: cliInvocation.env,
        stdio: ['ignore', 'pipe', 'pipe']
      })
      let stdout = ''
      let stderr = ''
      let outputBytes = 0
      let settled = false
      let timer
      const fail = (error) => {
        if (settled) {

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Parse the JSON in the message — it contains result.error / result.code describing the RPC-level refusal.
  2. Re-list the resource (e.g. 'terminal list') and retry with fresh handles; stale handles are the most common cause.
  3. If the error is a precondition/state error, serialize competing runs so they do not mutate the same terminals concurrently.
  4. Check remote-vs-local version skew (status.result.runtime.appVersion) since newer RPCs may reject older call shapes.

Example fix

// before
if (parsed.ok === false) {
  throw new Error(`${commandLabel} ${args.join(' ')} ok=false: ${JSON.stringify(parsed)}`)
}

// after
if (parsed.ok === false) {
  const code = parsed.error?.code ?? 'UNKNOWN'
  const msg = parsed.error?.message ?? JSON.stringify(parsed)
  throw new Error(`${commandLabel} ${args.join(' ')} ok=false [${code}]: ${msg}`)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (parsed && parsed.ok === false) {
  throw new Error(`RPC ${args.join(' ')} rejected [${parsed.error?.code}]: ${parsed.error?.message}`)
}

Type guard

const isRpcError = (p) => p && p.ok === false

Try / catch

try {
  return orcaJsonSync(args)
} catch (e) {
  if (/ok=false/.test(e.message) && /NOT_FOUND|STALE/.test(e.message)) {
    return orcaJsonSync(args) // retry once after re-list
  }
  throw e
}

Prevention

When it happens

Trigger: The orca RPC handler ran and returned a structured error: a requested resource (terminal/worktree/session) was not found, a state transition was invalid, an internal precondition failed, or the operation was rejected for safety. The CLI still exits 0 because it successfully delivered the response.

Common situations: Switching to a terminal that disconnected between list and switch, opening a flood terminal whose worktree vanished, a concurrent run mutating shared state, or a version where the RPC rejects an argument the older version accepted.

Related errors


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