Hmbown/CodeWhale · error · Error

Invalid pet duration.

Error message

Invalid pet duration.

What it means

compilePetTelemetry requires durationMs to be a finite, non-negative number of milliseconds; anything else (NaN, Infinity, negative) is rejected because bucket allocation is derived arithmetically from it. originMs is subtracted afterwards, so the raw value must still be valid on its own.

Solutions

  1. Coerce the duration before calling: Number.isFinite(d) && d >= 0, else clamp to 0.
  2. Fix the upstream timestamp so end - start is a valid non-negative number of ms.
  3. Sanitize JSON-sourced durations with Number(...) and reject NaN at parse time.
  4. Normalize clock sources (use a single monotonic clock) to avoid skew-induced negatives.

Example fix

// before
compilePetTelemetry(events, endTs - startTs);
// after
const d = Number(endTs) - Number(startTs);
compilePetTelemetry(events, Number.isFinite(d) && d >= 0 ? d : 0, firstSequence, originMs);
Defensive patterns

Strategy: validation

Validate before calling

const d = end - start;
if (!Number.isFinite(d) || d < 0) throw new Error('bad duration'); // fix timestamps upstream
compilePetTelemetry(events, d, firstSequence, originMs);

Type guard

const isValidDuration = (d) => typeof d === 'number' && Number.isFinite(d) && d >= 0;

Try / catch

try { compilePetTelemetry(events, durationMs, firstSequence, originMs); }
catch (e) { if (e.message === 'Invalid pet duration.') { compilePetTelemetry(events, 0, firstSequence, originMs); } else throw e; }

Prevention

When it happens

Trigger: Passing durationMs as NaN/Infinity/negative — e.g. computing it from an unset end timestamp (undefined - start = NaN), a failed Date parse, a negative elapsed due to clock skew, or passing seconds instead of milliseconds producing a wrong-but-finite value (that one won't throw; NaN/negative will).

Common situations: Clock skew between producer and consumer making end<start; uninitialized end-time fields; string durations ('1200') from JSON that slipped through; new Date('garbage').getTime().

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


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

Appendix: source

Thrown at pet/ios/Resources/pet-native.js:1171

        this.sequence = packet.sequence;
        if (previous === undefined || packet.sequence <= previous)
            return;
        return packet;
    }
}
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));

View on GitHub (pinned to 433685b202)