stablyai/orca · error · Error

Terminal history seed transfer exceeds retained byte limit

Error message

Terminal history seed transfer exceeds retained byte limit

What it means

Thrown by TerminalHistorySeedTransferRegistry.append when appending a chunk would push cumulative retained bytes over maxRetainedBytes (default 200 MB, TERMINAL_HISTORY_CHECKPOINT_MAX_BYTES) or would exceed the manifest's declared total codeUnits. The registry tracks retainedBytes across all transfers to bound daemon memory; a single append that breaches either budget is rejected and the transfer is left consistent.

Source

Thrown at src/main/daemon/terminal-history-seed-transfer-registry.ts:67

  }

  append(ownerId: string, transferId: string, index: number, data: string): void {
    const transfer = this.getOwned(ownerId, transferId)
    if (transfer.finished) {
      throw new Error('Terminal history seed transfer is already finished')
    }
    if (index !== transfer.chunks.length || index >= transfer.manifest.chunkCount) {
      throw new Error('Terminal history seed chunk sequence mismatch')
    }
    if (data.length === 0 || data.length > TERMINAL_HISTORY_SEED_CHUNK_CODE_UNITS) {
      throw new Error('Terminal history seed chunk size is invalid')
    }
    const utf8Bytes = Buffer.byteLength(data, 'utf8')
    if (
      transfer.codeUnits + data.length > transfer.manifest.codeUnits ||
      this.retainedBytes + utf8Bytes > this.maxRetainedBytes
    ) {
      throw new Error('Terminal history seed transfer exceeds retained byte limit')
    }
    transfer.chunks.push(data)
    transfer.codeUnits += data.length
    transfer.utf8Bytes += utf8Bytes
    transfer.hash.update(Buffer.from(data, 'utf16le'))
    this.retainedBytes += utf8Bytes
    this.refreshExpiry(transferId, transfer)
  }

  finish(ownerId: string, transferId: string): void {
    const transfer = this.getOwned(ownerId, transferId)
    if (transfer.finished) {
      throw new Error('Terminal history seed transfer is already finished')
    }
    if (
      transfer.chunks.length !== transfer.manifest.chunkCount ||
      transfer.codeUnits !== transfer.manifest.codeUnits
    ) {

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Re-measure the seed with measureTerminalHistorySeed and send a manifest whose codeUnits matches the actual chunks exactly.
  2. Reduce the number of concurrent transfers so retained bytes stay under 200 MB.
  3. Chunk the seed with iterateTerminalHistorySeedChunks so chunk sizes and totals match the manifest.
  4. Abort and restart the transfer with a corrected manifest if the size estimate was wrong.

Example fix

// before: manifest with a guessed codeUnits
registry.start(id, { chunkCount, codeUnits: guessed, sha256 })

// after: measure exact metrics
const { chunkCount, codeUnits, sha256 } = measureTerminalHistorySeed(segments)
registry.start(id, { chunkCount, codeUnits, sha256 })
Defensive patterns

Strategy: validation

Validate before calling

import { measureTerminalHistorySeed, iterateTerminalHistorySeedChunks } from './terminal-history-seed-chunks'
// Build the manifest from the exact chunks you will send
const metrics = measureTerminalHistorySeed(segments)
// Then verify each append stays within manifest.codeUnits and global budget
function appendFits(transferCodeUnits: number, chunk: string, manifestCodeUnits: number): boolean {
  return transferCodeUnits + chunk.length <= manifestCodeUnits
}

Type guard

function isSeedRetainedByteLimit(e: unknown): boolean {
  return e instanceof Error && e.message === 'Terminal history seed transfer exceeds retained byte limit'
}

Try / catch

try {
  registry.append(ownerId, transferId, index, data)
} catch (e) {
  if (e instanceof Error && e.message === 'Terminal history seed transfer exceeds retained byte limit') {
    // abort and restart with a corrected manifest / fewer concurrent transfers
    registry.abort(ownerId, transferId)
  } else { throw e }
}

Prevention

When it happens

Trigger: append(ownerId, transferId, index, data) where this.retainedBytes + utf8Bytes(data) > maxRetainedBytes, or transfer.codeUnits + data.length > manifest.codeUnits. The manifest declared fewer code units than the client is sending, or total memory is saturated.

Common situations: A manifest whose codeUnits understates the actual seed size; many concurrent transfers whose retained bytes collectively exceed 200 MB; a client re-chunking with different boundaries than the manifest measured.

Related errors


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