Hmbown/CodeWhale · error · Error
Missing Engine index.
Error message
Missing Engine index.
What it means
The index() helper in observe converts the required non-negative safe-integer e.index into a span key suffix for message/thinking events. It throws 'Missing Engine index.' when index is absent or not a safe integer. Note the fields-level check only validates index when present; this throw fires when an event kind that needs index (message_started, response_delta, message_complete, thinking_*) lacks it entirely.
Solutions
- Always attach a non-negative safe-integer index to message/thinking lifecycle and delta events
- Parse the index at the bridge boundary with Number and validate Number.isSafeInteger before observing
- Skip events that legitimately carry no index instead of forwarding them to these event kinds
Example fix
// before
telemetry.observe({ event: 'response_delta', channel: 'text' }, at); // no index
// after
telemetry.observe({ event: 'response_delta', index: messageIndex, channel: 'text' }, at); Defensive patterns
Strategy: validation
Validate before calling
const NEEDS_INDEX = new Set(['message_started','message_complete','thinking_started','thinking_complete','response_delta']);
if (NEEDS_INDEX.has(e.event) && !Number.isSafeInteger(e.index)) throw new Error('event requires index'); Try / catch
try {
telemetry.observe(meta, at);
} catch (err) {
if (err.message === 'Missing Engine index.') { console.warn('dropping event without index', meta); return; }
throw err;
} Prevention
- Attach the message/thinking index to every lifecycle and delta event
- Validate index with Number.isSafeInteger before observing
- Never stringify the index — keep it numeric until the adapter converts it
When it happens
Trigger: Sending message_started/message_complete/thinking_started/thinking_complete/response_delta without an index field; index present as undefined via an explicit property; index as a string ('3') or float (3.5) reaching this helper.
Common situations: A delta event stream where the first delta omits the message index; a producer switching from numeric to string ids after a protocol change; optional-chaining bugs leaving index undefined.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Missing Engine .
- Missing Engine .
- Missing Engine index.
- Invalid Engine pet clock.
- Invalid Engine pet metadata.
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/598a85b6954304de.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tui/pet_watch/pet-native.js:1746
if (!Number.isFinite(at) || at < this.lastTime || at > pet_sim_js_1.PET_MAX_SECONDS * 1000)
throw new Error('Invalid Engine pet clock.');
if (!value || typeof value !== 'object' || Array.isArray(value))
throw new Error('Invalid Engine pet metadata.');
const e = value;
const allowed = ['event', 'index', 'channel', 'tool_call_id', 'tool_name', 'id', 'worker_status', 'failed'];
if (Object.keys(e).some(k => !allowed.includes(k)) || typeof e.event !== 'string'
|| Object.values(e).some(v => typeof v === 'string' && v.length > 4096)
|| e.channel !== undefined && !['text', 'reasoning'].includes(e.channel)
|| ['tool_call_id', 'tool_name', 'id', 'worker_status'].some(k => e[k] !== undefined && typeof e[k] !== 'string')
|| e.failed !== undefined && typeof e.failed !== 'boolean'
|| e.index !== undefined && (!Number.isSafeInteger(e.index) || e.index < 0))
throw new Error('Invalid Engine pet metadata fields.');
this.lastTime = at;
this.events = this.events.filter(span => span.endTime >= at - 12_800);
const id = (field) => { const s = e[field]; if (typeof s !== 'string' || !s)
throw new Error(`Missing Engine ${field}.`); return s; };
const index = () => { if (!Number.isSafeInteger(e.index))
throw new Error('Missing Engine index.'); return String(e.index); };
const start = (key, name, category, agentId) => {
if (this.active.size >= 256 && !this.active.has(key))
throw new Error('Too many active Engine pet spans.');
this.active.set(key, this.add(name, category, at, agentId));
};
const finish = (key) => { this.pulse(key, at); this.active.delete(key); };
switch (e.event) {
case 'turn_started':
this.active.clear();
this.waiting = undefined;
break;
case 'message_started':
start(`message:${index()}`, 'assistant_message', 'communication');
this.waiting = undefined;
break;
case 'thinking_started':
start(`thinking:${index()}`, 'thinking', 'reasoning');
this.waiting = undefined;View on GitHub (pinned to 73e0f67d83)