Hmbown/CodeWhale · error · Error

Pet input exceeds 250000 events.

Error message

Pet input exceeds 250000 events.

What it means

Guard at the top of compilePetTelemetry: fires when the input event array has more than 250,000 WhaleEvents. Compilation is O(events), so this cap protects against pathological traces; the caller must pre-bucket or trim input before compiling.

Solutions

  1. Chunk the input into ≤250,000-event slices and call compilePetTelemetry per slice, merging buckets
  2. Flush the event buffer more frequently so batches stay small
  3. Filter or downsample events before compiling
  4. Raise the cap locally only if you truly need giant batches (fork/patch) — the default is intentional

Example fix

// before
const buckets = compilePetTelemetry(allEvents);
// after
const buckets = [];
for (let i = 0; i < allEvents.length; i += 250_000)
  buckets.push(...compilePetTelemetry(allEvents.slice(i, i + 250_000)));
Defensive patterns

Strategy: validation

Validate before calling

if (events.length > 250_000) {
  for (let i = 0; i < events.length; i += 250_000) compilePetTelemetry(events.slice(i, i + 250_000));
} else {
  compilePetTelemetry(events);
}

Type guard

null

Try / catch

try {
  compilePetTelemetry(events);
} catch (e) {
  if (e.message === 'Pet input exceeds 250000 events.') {
    chunk(events, 250_000).forEach(chunkEvents => compilePetTelemetry(chunkEvents));
  } else throw e;
}

Prevention

When it happens

Trigger: Calling compilePetTelemetry with an input array whose length exceeds 250,000 — e.g. feeding a whole day of raw events into one call instead of per-bin batches.

Common situations: Backfill jobs that batch an entire retention window; an event collector that never flushed; merging several traces' events into a single compile call.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/4a11a6d3907045ff. Report an issue: GitHub.

Appendix: source

Thrown at pet/src/core/pet-telemetry.ts:71

    let packet: unknown;
    try { packet = JSON.parse(line); validatePetBucket(packet); }
    catch (error) { this.reset(); throw error; }
    const previous = this.sequence; this.sequence = packet.sequence;
    if (previous === undefined || packet.sequence <= previous) return;
    return packet;
  }
}

const order = (a: string, b: string) => a < b ? -1 : a > b ? 1 : 0;
const keyOf = (e: WhaleEvent) => JSON.stringify([e.traceId, e.id]);
const isContainer = (e: WhaleEvent) => e.attributes['whalesong.container'] === true
  || e.attributes['codewhale.container'] === true;

/** Compile a single trace. Unknown-duration spans provide onsets, not occupancy.
 * Updates of the same trace/id replace earlier snapshots rather than double count.
 * An endpoint onset gets its own bucket; intervals use [start, end). */
export function compilePetTelemetry(input: readonly WhaleEvent[], durationMs = 0, firstSequence = 0, originMs = 0): PetBucket[] {
  if (input.length > 250_000) throw new Error('Pet input exceeds 250000 events.');
  if (!Number.isFinite(durationMs) || durationMs < 0) throw new Error('Invalid pet duration.');
  if (!Number.isSafeInteger(firstSequence) || firstSequence < 0) throw new Error('Invalid first pet bucket.');
  if (!Number.isFinite(originMs)) throw new Error('Invalid pet clock origin.');
  durationMs = Math.max(0, durationMs - originMs);
  const unique = new Map<string, WhaleEvent>();
  const traces = new Set<string>();
  for (const e of input) {
    if (e.schemaVersion !== 1 || !e.id || !e.traceId || !CATEGORIES.includes(e.category)
      || !Number.isFinite(e.startTime) || !Number.isFinite(e.endTime)
      || e.startTime < 0 || e.endTime < e.startTime || !e.attributes)
      throw new Error('Invalid event-v1 pet input. Import through importTrace first.');
    traces.add(e.traceId); unique.set(keyOf(e), e);
  }
  if (traces.size > 1) throw new Error('Select one trace for the pet.');
  const parents = new Set([...unique.values()].filter(e => e.parentId).map(e => e.parentId!));
  const events = [...unique.values()].filter(e => !isContainer(e)
    && !(e.category === 'orchestration' && parents.has(e.id)))
    .map(e => ({ ...e, startTime: e.startTime - originMs, endTime: (e.openEnded ? e.startTime : e.endTime) - originMs,

View on GitHub (pinned to 433685b202)