Hmbown/CodeWhale · error · Error
Invalid first pet bucket.
Error message
Invalid first pet bucket.
What it means
compilePetTelemetry requires firstSequence to be a safe non-negative integer, because it is used directly as the starting bucket sequence number. Floats, negatives, or numbers beyond Number.MAX_SAFE_INTEGER throw this error.
Solutions
- Floor and validate: Math.floor(firstSequence), and clamp at 0 before calling
- Pass the explicit default 0 when starting a fresh tape
- Compute sequence numbers with Math.floor(originMs / PET_BIN_MS) and assert Number.isSafeInteger
- Skip compilation when the computed first sequence is invalid and log the cause
Example fix
// before compilePetTelemetry(events, duration, elapsedMs / PET_BIN_MS); // after const first = Math.max(0, Math.floor(elapsedMs / PET_BIN_MS)); compilePetTelemetry(events, duration, Number.isSafeInteger(first) ? first : 0);
Defensive patterns
Strategy: validation
Validate before calling
const first = Math.max(0, Math.floor(elapsedMs / PET_BIN_MS));
if (!Number.isSafeInteger(first)) throw new Error('bad firstSequence before compile'); Type guard
function isValidFirstSequence(n: unknown): n is number {
return typeof n === 'number' && Number.isSafeInteger(n) && n >= 0;
} Try / catch
try {
compilePetTelemetry(events, duration, firstSequence);
} catch (e) {
if (e.message === 'Invalid first pet bucket.') {
compilePetTelemetry(events, duration, 0); // restart tape numbering
} else throw e;
} Prevention
- Always Math.floor computed bucket indices
- Clamp negatives to 0
- Assert Number.isSafeInteger before passing sequence offsets
When it happens
Trigger: Calling compilePetTelemetry with firstSequence = -1, a fractional value from division, NaN, or an unbounded computed offset (e.g. ms-since-epoch divided by PET_BIN_MS without flooring/clamping).
Common situations: Computing the first bucket as Date.now()/PET_BIN_MS and getting a float; an uninitialized variable defaulting to NaN; a negative offset from a clock-origin subtraction gone wrong.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Invalid Engine pet clock.
- Invalid Engine pet metadata.
- Invalid Engine pet metadata.
- Invalid Engine pet metadata fields.
- Invalid failure observation time.
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/c6edaff353f2fe1a.
Report an issue: GitHub.
Appendix: source
Thrown at pet/src/core/pet-telemetry.ts:73
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,
attributes: e.attributes['whalesong.error_onset_ms'] === undefined ? e.attributes
: { ...e.attributes, 'whalesong.error_onset_ms': errorOnsetOf(e) - originMs } }))View on GitHub (pinned to 433685b202)