Hmbown/CodeWhale · error · Error
Invalid pet clock origin.
Error message
Invalid pet clock origin.
What it means
The pet replay ingestor in pet-native.js validates a numeric clock origin via Number.isFinite(originMs) before replaying events. This error means the originMs argument passed to the pet build/score entry point is not a finite number (NaN, Infinity, undefined, string, etc.). The library throws early so bin math (durations and timestamps shifted by originMs) stays well-defined.
Solutions
- Pass a finite epoch-milliseconds number as originMs, e.g. Date.parse(traceStart) for a date string.
- Check the value with Number.isFinite(originMs) at the call site before invoking the API.
- If the origin comes from config or metadata, verify it is present and numeric; fall back to 0 for a zero-based trace.
Example fix
// before
buildPet(trace, { originMs: trace.startTimeISO });
// after
buildPet(trace, { originMs: Date.parse(trace.startTimeISO) }); Defensive patterns
Strategy: validation
Validate before calling
if (!Number.isFinite(originMs)) throw new TypeError('originMs must be a finite number');
const origin = typeof origin === 'string' ? Date.parse(origin) : origin; Type guard
const isFiniteNumber = (v) => typeof v === 'number' && Number.isFinite(v);
Prevention
- Always convert dates with Date.parse() or Date.getTime() before passing an origin
- Default originMs to 0 when absent
- Keep trace timestamps relative, not absolute epoch values
When it happens
Trigger: Calling the pet replay/builder function with an originMs argument that is NaN, Infinity, null, or a non-numeric value (e.g. a Date object not converted with .getTime(), or an undefined variable).
Common situations: Developers passing Date objects or ISO strings instead of epoch milliseconds, reading the origin from an unpopulated config field, or JSON round-trips that turned a number into null.
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
- Signal duration must be finite and nonnegative.
- 1
- A pinned task provider requires an explicit model
- A positive pull request number is required
- A provider and page loader are required.
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/ec081c2827fbde7f.
Report an issue: GitHub.
Appendix: source
Thrown at pet/ios/Resources/pet-native.js:1175
}
}
exports.PetLiveTape = PetLiveTape;
const order = (a, b) => a < b ? -1 : a > b ? 1 : 0;
const keyOf = (e) => JSON.stringify([e.traceId, e.id]);
const isContainer = (e) => 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). */
function compilePetTelemetry(input, durationMs = 0, firstSequence = 0, originMs = 0) {
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();
const traces = new Set();
for (const e of input) {
if (e.schemaVersion !== 1 || !e.id || !e.traceId || !model_js_1.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.attributesView on GitHub (pinned to 433685b202)