stablyai/orca · error · Error

History limit must be a positive integer, got ${limit}

Error message

History limit must be a positive integer, got ${limit}

What it means

BoundedLiveFreezeHistory is a fixed-capacity ring buffer that records live-freeze timing entries. The constructor enforces that 'limit' be a positive integer because the buffer uses it both as the array length cap and as the modulus in the wraparound index (#nextIndex = (next + 1) % limit). A non-integer, zero, or negative value would corrupt the modulus math or never allow insertion. The throw protects the invariant that add() can always overwrite in O(1).

Source

Thrown at config/scripts/live-freeze-bounded-history.mjs:9

export class BoundedLiveFreezeHistory {
  #entries = []
  #limit
  #nextIndex = 0
  #totalCount = 0

  constructor(limit) {
    if (!Number.isInteger(limit) || limit <= 0) {
      throw new Error(`History limit must be a positive integer, got ${limit}`)
    }
    this.#limit = limit
  }

  add(entry) {
    this.#totalCount += 1
    if (this.#entries.length < this.#limit) {
      this.#entries.push(entry)
      return
    }
    this.#entries[this.#nextIndex] = entry
    this.#nextIndex = (this.#nextIndex + 1) % this.#limit
  }

  get retainedCount() {
    return this.#entries.length
  }

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Pass a hardcoded positive integer literal (e.g. new BoundedLiveFreezeHistory(100)) when the capacity is a fixed sampling size.
  2. If the limit comes from env/config, coerce and clamp before construction: const limit = Math.max(1, Math.trunc(Number(raw) || 0)).
  3. Add a runtime assertion in the caller that prints which input produced the bad limit so the source of the bad value is traceable.

Example fix

// before
const history = new BoundedLiveFreezeHistory(readEnv('FREEZE_HISTORY_SIZE'))

// after
const raw = Number(readEnv('FREEZE_HISTORY_SIZE'))
if (!Number.isInteger(raw) || raw <= 0) {
  throw new Error(`FREEZE_HISTORY_SIZE must be a positive integer, got ${raw}`)
}
const history = new BoundedLiveFreezeHistory(raw)
Defensive patterns

Strategy: validation

Validate before calling

function assertPositiveInt(limit, name = 'limit') {
  if (!Number.isInteger(limit) || limit <= 0) {
    throw new TypeError(`${name} must be a positive integer, got ${limit}`)
  }
}
// caller:
assertPositiveInt(rawLimit, 'FREEZE_HISTORY_SIZE')
const history = new BoundedLiveFreezeHistory(rawLimit)

Type guard

const isPositiveInteger = (n) => Number.isInteger(n) && n > 0

Try / catch

try {
  history = new BoundedLiveFreezeHistory(limit)
} catch (e) {
  throw new Error(`Bad history config (${limit}): ${e.message}`)
}

Prevention

When it happens

Trigger: Constructing the history with new BoundedLiveFreezeHistory(limit) where limit is 0, negative, a float like 2.5, a numeric string like "100", NaN, or undefined. The check Number.isInteger(limit) && limit > 0 is what fails.

Common situations: Reading the capacity from an env var or CLI flag without coercion (e.g. passing a string), computing it dynamically and getting 0 on an empty result set, or passing Math.floor of a value that is already corrupt. In the freeze repro scripts the limit is often a constant like 100, but a misconfigured env override can inject a bad value.

Related errors


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