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

  1. Always attach a non-negative safe-integer index to message/thinking lifecycle and delta events
  2. Parse the index at the bridge boundary with Number and validate Number.isSafeInteger before observing
  3. 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

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


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)