{"record":{"id":"4a11a6d3907045ff","repo":"Hmbown/CodeWhale","slug":"pet-input-exceeds-250000-events-telemetry","errorCode":null,"errorMessage":"Pet input exceeds 250000 events.","messagePattern":"Pet input exceeds 250000 events\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/src/core/pet-telemetry.ts","lineNumber":71,"sourceCode":"    let packet: unknown;\n    try { packet = JSON.parse(line); validatePetBucket(packet); }\n    catch (error) { this.reset(); throw error; }\n    const previous = this.sequence; this.sequence = packet.sequence;\n    if (previous === undefined || packet.sequence <= previous) return;\n    return packet;\n  }\n}\n\nconst order = (a: string, b: string) => a < b ? -1 : a > b ? 1 : 0;\nconst keyOf = (e: WhaleEvent) => JSON.stringify([e.traceId, e.id]);\nconst isContainer = (e: WhaleEvent) => e.attributes['whalesong.container'] === true\n  || e.attributes['codewhale.container'] === true;\n\n/** Compile a single trace. Unknown-duration spans provide onsets, not occupancy.\n * Updates of the same trace/id replace earlier snapshots rather than double count.\n * An endpoint onset gets its own bucket; intervals use [start, end). */\nexport function compilePetTelemetry(input: readonly WhaleEvent[], durationMs = 0, firstSequence = 0, originMs = 0): PetBucket[] {\n  if (input.length > 250_000) throw new Error('Pet input exceeds 250000 events.');\n  if (!Number.isFinite(durationMs) || durationMs < 0) throw new Error('Invalid pet duration.');\n  if (!Number.isSafeInteger(firstSequence) || firstSequence < 0) throw new Error('Invalid first pet bucket.');\n  if (!Number.isFinite(originMs)) throw new Error('Invalid pet clock origin.');\n  durationMs = Math.max(0, durationMs - originMs);\n  const unique = new Map<string, WhaleEvent>();\n  const traces = new Set<string>();\n  for (const e of input) {\n    if (e.schemaVersion !== 1 || !e.id || !e.traceId || !CATEGORIES.includes(e.category)\n      || !Number.isFinite(e.startTime) || !Number.isFinite(e.endTime)\n      || e.startTime < 0 || e.endTime < e.startTime || !e.attributes)\n      throw new Error('Invalid event-v1 pet input. Import through importTrace first.');\n    traces.add(e.traceId); unique.set(keyOf(e), e);\n  }\n  if (traces.size > 1) throw new Error('Select one trace for the pet.');\n  const parents = new Set([...unique.values()].filter(e => e.parentId).map(e => e.parentId!));\n  const events = [...unique.values()].filter(e => !isContainer(e)\n    && !(e.category === 'orchestration' && parents.has(e.id)))\n    .map(e => ({ ...e, startTime: e.startTime - originMs, endTime: (e.openEnded ? e.startTime : e.endTime) - originMs,","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/src/core/pet-telemetry.ts#L53-L89","documentation":"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.","triggerScenarios":"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.","commonSituations":"Backfill jobs that batch an entire retention window; an event collector that never flushed; merging several traces' events into a single compile call.","solutions":["Chunk the input into ≤250,000-event slices and call compilePetTelemetry per slice, merging buckets","Flush the event buffer more frequently so batches stay small","Filter or downsample events before compiling","Raise the cap locally only if you truly need giant batches (fork/patch) — the default is intentional"],"exampleFix":"// before\nconst buckets = compilePetTelemetry(allEvents);\n// after\nconst buckets = [];\nfor (let i = 0; i < allEvents.length; i += 250_000)\n  buckets.push(...compilePetTelemetry(allEvents.slice(i, i + 250_000)));","handlingStrategy":"validation","validationCode":"if (events.length > 250_000) {\n  for (let i = 0; i < events.length; i += 250_000) compilePetTelemetry(events.slice(i, i + 250_000));\n} else {\n  compilePetTelemetry(events);\n}","typeGuard":"null","tryCatchPattern":"try {\n  compilePetTelemetry(events);\n} catch (e) {\n  if (e.message === 'Pet input exceeds 250000 events.') {\n    chunk(events, 250_000).forEach(chunkEvents => compilePetTelemetry(chunkEvents));\n  } else throw e;\n}","preventionTips":["Flush event buffers before they reach 250k","Batch compiles per time window rather than per retention period","Downsample or filter events before compiling"],"tags":["limits","batching","telemetry"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}