stablyai/orca · error · Error
Too many pending terminal history seed transfers
Error message
Too many pending terminal history seed transfers
What it means
Thrown by TerminalHistorySeedTransferRegistry.start when the number of in-flight transfers has reached MAX_TRANSFERS (8). Each transfer holds chunks in memory until finish/take or a 30s TTL, so the registry caps concurrency to bound retained bytes. Starting a ninth transfer is refused.
Source
Thrown at src/main/daemon/terminal-history-seed-transfer-registry.ts:33
utf8Bytes: number
hash: ReturnType<typeof createHash>
finished: boolean
timer: ReturnType<typeof setTimeout>
}
export class TerminalHistorySeedTransferRegistry {
private transfers = new Map<string, Transfer>()
private retainedBytes = 0
constructor(
private readonly maxRetainedBytes = TERMINAL_HISTORY_CHECKPOINT_MAX_BYTES,
private readonly transferTtlMs = TRANSFER_TTL_MS
) {}
start(ownerId: string, manifest: TerminalHistorySeedTransferManifest): string {
this.validateManifest(manifest)
if (this.transfers.size >= MAX_TRANSFERS) {
throw new Error('Too many pending terminal history seed transfers')
}
const transferId = randomUUID()
const timer = setTimeout(() => this.delete(transferId), this.transferTtlMs)
timer.unref()
this.transfers.set(transferId, {
ownerId,
manifest: { ...manifest },
chunks: [],
codeUnits: 0,
utf8Bytes: 0,
hash: createHash('sha256'),
finished: false,
timer
})
return transferId
}
append(ownerId: string, transferId: string, index: number, data: string): void {View on GitHub (pinned to 1136503c6a)
Solutions
- Complete (finish + take) or abort existing transfers before starting new ones; do not let transfers leak.
- Serialize seed transfers across sessions so you never exceed 8 in flight.
- Wait for the 30s TTL to reap stale transfers, then retry start.
- Call clearOwner(clientId) when a client disconnects to reclaim its transfers.
Example fix
// before: open a transfer per tab without bounding
for (const tab of tabs) {
const id = registry.start(clientId, metrics)
}
// after: bound concurrency and complete each before the next
for (const batch of chunks(tabs, 8)) {
const ids = batch.map(t => registry.start(clientId, measure(t)))
// append + finish + take each, then proceed
} Defensive patterns
Strategy: retry
Validate before calling
// Bound in-flight transfers before starting a new one (registry max is 8)
if (pendingTransferCount >= 8) {
// wait for some to finish/expire, or serialize
} Type guard
function isTooManySeedTransfers(e: unknown): boolean {
return e instanceof Error && e.message === 'Too many pending terminal history seed transfers'
} Try / catch
try {
return registry.start(ownerId, manifest)
} catch (e) {
if (e instanceof Error && e.message === 'Too many pending terminal history seed transfers') {
await waitForTransferSlot(registry) // complete/abort one, or wait ~TTL
return registry.start(ownerId, manifest)
}
throw e
} Prevention
- Complete (finish + take) or abort transfers promptly; do not leak them.
- Serialize seed transfers across sessions to stay under the cap of 8.
- Call clearOwner on client disconnect to reclaim its transfers.
When it happens
Trigger: start() called while transfers.size >= 8, i.e., 8 transfers are already pending (not yet finished, taken, aborted, or expired).
Common situations: Bulk-restoring many terminal sessions at once (e.g., after a crash restoring 9+ tabs) each starting a seed transfer; transfers leaked because finish/take was never called and the 30s TTL has not yet elapsed; a client bug opening transfers without completing them.
Related errors
- Terminal history seed transfer exceeds retained byte limit
- Terminal history seed transfer digest mismatch
- ${tag} does not contain ${name}
- Terminal input is locked by another client.
- Failed to load commit history
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/8d7b1cb9a85b5656.
Report an issue: GitHub.