{"record":{"id":"94f42a89757cf623","repo":"Hmbown/CodeWhale","slug":"invalid-pet-duration","errorCode":null,"errorMessage":"Invalid pet duration.","messagePattern":"Invalid pet duration\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tui/pet_watch/pet-native.js","lineNumber":1171,"sourceCode":"        this.sequence = packet.sequence;\n        if (previous === undefined || packet.sequence <= previous)\n            return;\n        return packet;\n    }\n}\nexports.PetLiveTape = PetLiveTape;\nconst order = (a, b) => a < b ? -1 : a > b ? 1 : 0;\nconst keyOf = (e) => JSON.stringify([e.traceId, e.id]);\nconst isContainer = (e) => e.attributes['whalesong.container'] === true\n    || e.attributes['codewhale.container'] === true;\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). */\nfunction compilePetTelemetry(input, durationMs = 0, firstSequence = 0, originMs = 0) {\n    if (input.length > 250_000)\n        throw new Error('Pet input exceeds 250000 events.');\n    if (!Number.isFinite(durationMs) || durationMs < 0)\n        throw new Error('Invalid pet duration.');\n    if (!Number.isSafeInteger(firstSequence) || firstSequence < 0)\n        throw new Error('Invalid first pet bucket.');\n    if (!Number.isFinite(originMs))\n        throw new Error('Invalid pet clock origin.');\n    durationMs = Math.max(0, durationMs - originMs);\n    const unique = new Map();\n    const traces = new Set();\n    for (const e of input) {\n        if (e.schemaVersion !== 1 || !e.id || !e.traceId || !model_js_1.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);\n        unique.set(keyOf(e), e);\n    }\n    if (traces.size > 1)\n        throw new Error('Select one trace for the pet.');\n    const parents = new Set([...unique.values()].filter(e => e.parentId).map(e => e.parentId));","sourceCodeStart":1153,"sourceCodeEnd":1189,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tui/pet_watch/pet-native.js#L1153-L1189","documentation":"compilePetTelemetry() validates its durationMs parameter: it must be a finite, non-negative number of milliseconds. NaN, Infinity, negative values, or non-numeric input mean the caller computed an invalid trace duration, so compilation is refused.","triggerScenarios":"Calling compilePetTelemetry with durationMs as NaN (e.g. from an invalid Date or arithmetic on undefined), Infinity, a negative number, or a string — e.g. durationMs = end - start where start/end are undefined or strings.","commonSituations":"Timestamps parsed from malformed telemetry rows yielding NaN; unit mistakes (seconds vs milliseconds producing negative or tiny values); a Date.now() typo or missing field making end - start negative; JSON fields serialized as strings.","solutions":["Clamp/validate before calling: pass Number.isFinite(d) && d >= 0 ? d : 0.","Fix the timestamp source so end - start is a finite non-negative number (parse with Number() or Date.parse, default missing fields).","Check units: ensure both endpoints are in milliseconds and correctly ordered.","If origin offsetting is intended, note durationMs is reduced by originMs after validation — pass a duration that stays non-negative after that subtraction."],"exampleFix":"// before\nconst durationMs = end - start; // NaN or negative when fields missing\ncompilePetTelemetry(events, durationMs);\n// after\nconst raw = end - start;\nconst durationMs = Number.isFinite(raw) && raw >= 0 ? raw : 0;\ncompilePetTelemetry(events, durationMs);","handlingStrategy":"validation","validationCode":"function isValidDuration(ms) {\n  return typeof ms === 'number' && Number.isFinite(ms) && ms >= 0;\n}\nif (!isValidDuration(durationMs)) durationMs = 0;","typeGuard":"function isFiniteNonNegative(v) {\n  return typeof v === 'number' && Number.isFinite(v) && v >= 0;\n}","tryCatchPattern":"try {\n  compilePetTelemetry(events, durationMs);\n} catch (e) {\n  if (e.message === 'Invalid pet duration.') {\n    compilePetTelemetry(events, 0); // fall back to onset-only buckets\n  } else throw e;\n}","preventionTips":["Validate timestamps before subtraction: Number.isFinite(start) && Number.isFinite(end) && end >= start.","Parse timestamps with Number()/Date.parse, never trust raw JSON strings.","Check unit consistency (milliseconds everywhere).","Remember durationMs is reduced by originMs; ensure it stays >= 0 after that."],"tags":["input-validation","telemetry","argument-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}