Hmbown/CodeWhale · error · Error
Invalid failure observation time.
Error message
Invalid failure observation time.
What it means
errorOnsetOf() extracts the failure observation timestamp from a telemetry event's 'whalesong.error_onset_ms' attribute, falling back to startTime when absent. When the attribute is present it must be a finite number not earlier than the event's startTime; otherwise the observation time is inconsistent with the event itself and would produce a negative-duration signal view. The library throws to keep error onsets anchored to a valid timeline position.
Solutions
- Fix the producer to emit whalesong.error_onset_ms as a finite number on the same clock as startTime, with onset >= startTime.
- If the attribute cannot be trusted, omit it entirely so errorOnsetOf falls back to e.startTime.
- At the ingestion boundary, coerce/validate the attribute (parse strings, drop values < startTime) before the event reaches errorOnsetOf.
- Synchronize clocks across the components that write startTime and error_onset_ms.
Example fix
// before e.attributes['whalesong.error_onset_ms'] = String(Date.now()); // string, different clock // after const onset = e.startTime + measuredDelayMs; e.attributes['whalesong.error_onset_ms'] = Math.max(onset, e.startTime); // number, same clock
Defensive patterns
Strategy: validation
Validate before calling
function safeErrorOnset(e) {
const t = e.attributes?.['whalesong.error_onset_ms'];
if (t === undefined) return e.startTime;
const n = Number(t);
return (typeof n === 'number' && Number.isFinite(n) && n >= e.startTime) ? n : e.startTime;
} Type guard
const hasValidOnset = (e) => e.attributes?.['whalesong.error_onset_ms'] === undefined || (typeof e.attributes['whalesong.error_onset_ms'] === 'number' && Number.isFinite(e.attributes['whalesong.error_onset_ms']) && e.attributes['whalesong.error_onset_ms'] >= e.startTime);
Try / catch
try {
const onset = errorOnsetOf(e);
} catch (err) {
if (err.message === 'Invalid failure observation time.') {
onset = e.startTime; // fall back to event start
} else throw err;
} Prevention
- Emit error_onset_ms as a number on the same clock as startTime
- Omit the attribute rather than writing an untrusted value
- Validate/coerce telemetry attributes at ingestion
- Keep clocks synchronized across components writing startTime and onset
When it happens
Trigger: Processing a telemetry event whose attributes['whalesong.error_onset_ms'] is a non-number (string from JSON logs), NaN/Infinity, or a value smaller than e.startTime — e.g. an onset stamped with a different clock or recorded before the event began.
Common situations: Log exporters serializing the attribute as a string; clock skew between the component writing onset_ms and the one writing startTime; a producer using epoch ms while startTime uses a monotonic or relative clock; hand-crafted test events.
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
- GitHub timestamp is invalid
- Invalid Engine pet clock.
- Invalid Engine pet metadata.
- Invalid Engine pet metadata.
- Invalid Engine pet metadata fields.
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/ba620b2a778ae8ba.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tui/pet_watch/pet-native.js:625
if (f.query) {
const q = f.query.toLowerCase();
// Search is deliberately content-aware but runs only over locally retained fields.
if (![e.name, e.id, e.agentId, e.model, e.tool, e.provider, e.category,
JSON.stringify(e.attributes), JSON.stringify(e.payload), JSON.stringify(e.raw)].filter(Boolean).join(' ').toLowerCase().includes(q))
return false;
}
return true;
}
const durationOf = (e) => Math.max(0, e.endTime - e.startTime);
exports.durationOf = durationOf;
/** An explicit failure receipt can arrive after a span began or ended. Keep
* its timestamp distinct from the operation onset in every signal view. */
function errorOnsetOf(e) {
const time = e.attributes['whalesong.error_onset_ms'];
if (time === undefined)
return e.startTime;
if (typeof time !== 'number' || !Number.isFinite(time) || time < e.startTime)
throw new Error('Invalid failure observation time.');
return time;
}
function stableHash(text, seed = 2166136261) {
let h = seed;
for (let i = 0; i < text.length; i++) {
h ^= text.charCodeAt(i);
h = Math.imul(h, 16777619);
}
return h >>> 0;
}
function quantile(a, q) {
if (!a.length)
return 0;
const s = [...a].sort((a, b) => a - b), x = Math.min(1, Math.max(0, q)) * (s.length - 1);
return s[Math.floor(x)] + (s[Math.ceil(x)] - s[Math.floor(x)]) * (x % 1);
}
function clamp(x, lo, hi) { return Math.max(lo, Math.min(hi, x)); }
function formatTime(ms, precise = false) {View on GitHub (pinned to 73e0f67d83)