stablyai/orca · error · Error
Need ≥2 terminals; got ${openTargets.length}. ${notes.join('
Error message
Need ≥2 terminals; got ${openTargets.length}. ${notes.join('; ')} What it means
Realistic-freeze repro requires at least two distinct terminal handles for its open/switch exercise. It unions created terminal handles with live ones, dedupes, then asserts length >= 2. Below that, the open/park/switch phases cannot meaningfully run.
Source
Thrown at config/scripts/live-remote-realistic-freeze-repro.mjs:229
)
phases.push({ phase: 'seed-flood', created: created.length })
}
// Prefer created floods for open pass; fill with existing live terminals.
let live = []
try {
live = listLiveTerminalHandles()
notes.push(`live terminals listed=${live.length}`)
} catch (error) {
notes.push(`terminal list failed: ${String(error).slice(0, 200)}`)
}
const openTargets = [...created.map((c) => c.handle), ...live.map((t) => t.handle)].filter(
(v, i, a) => typeof v === 'string' && a.indexOf(v) === i
)
if (openTargets.length < 2) {
throw new Error(`Need ≥2 terminals; got ${openTargets.length}. ${notes.join('; ')}`)
}
const openList = openTargets.slice(0, Math.min(openCount, openTargets.length))
// --- Phase: park — leave one session focused, rest accumulate flood while "away" ---
try {
const parkHandle = openList[0]
const parked = await orcaJsonAsync(['terminal', 'switch', '--terminal', parkHandle], {
timeoutMs: 60_000
})
notes.push(`park switch ms=${parked.elapsedMs.toFixed(0)} handle=${parkHandle}`)
} catch (error) {
notes.push(`park switch failed: ${String(error).slice(0, 200)}`)
}
console.log(`[realistic-freeze] idle ${idleMs}ms while remotes stream (user away / asleep)`)
const idleStarted = performance.now()
await sleep(idleMs)View on GitHub (pinned to 1136503c6a)
Solutions
- Set createCount >= 2 (or pre-open terminals) so the union yields at least two handles.
- Inspect the notes joined into the message — it records 'terminal list failed' and list counts that show whether list or create is the loss.
- Verify listLiveTerminalHandles reads the correct handle field for the remote orca version.
Example fix
// before
if (openTargets.length < 2) {
throw new Error(`Need >=2 terminals; got ${openTargets.length}. ${notes.join('; ')}`)
}
// after
if (openTargets.length < 2) {
throw new Error(`Need >=2 terminals; got ${openTargets.length}. created=${created.length} live=${live.length}. ${notes.join('; ')}`)
} Defensive patterns
Strategy: validation
Validate before calling
if (createCount + live.length < 2) {
throw new Error(`Need >=2 terminals; create=${createCount} live=${live.length}`)
} Type guard
const hasMinHandles = (arr, n = 2) => Array.isArray(arr) && arr.filter(h => typeof h === 'string').length >= n
Prevention
- Compute the union size before the open phase.
- Push created/live counts into notes for diagnosability.
- Confirm the live-list field name matches the remote orca version.
When it happens
Trigger: createCount is 0 or all creates failed and the live list returned < 2 handles; or the live-list call itself failed (caught and pushed to notes) leaving only the created set.
Common situations: Idle remote with a single terminal, terminal creation failing under load, a live-list field-name mismatch filtering all handles out, or running the open phase before any terminals exist.
Related errors
- Need ≥2 terminals to bulk-switch; got ${switchTargets.length
- invalid_argument
- Package version is not valid semver: ${baseVersion}
- Adhoc build timestamp is invalid.
- Adhoc label has no usable characters: ${JSON.stringify(label
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/17367d2de26d9cac.
Report an issue: GitHub.