Hmbown/CodeWhale · error · Error
Unsupported Engine pet event.
Error message
Unsupported Engine pet event.
What it means
observe dispatches on e.event and only recognizes the Engine lifecycle events it models (turn_started, message_*/thinking_*/response_delta, tool_call_*, agent_*, approval_required, user_input_required, turn_complete, error). Any other event string reaches the default case and throws 'Unsupported Engine pet event.' The adapter is deliberately strict: unknown protocol events must fail loudly rather than be silently ignored, so the pet sim never misreads activity.
Solutions
- Filter events to the supported set before calling observe, ignoring purely informational ones
- Extend the switch with the new event case when the protocol legitimately added it (and bump the adapter with the protocol change)
- Fix the event name spelling to match a supported variant
- Pre-decode with a mapping table from raw EventMsg type to adapter event names
Example fix
// before
telemetry.observe({ event: msg.type, ... }, at); // msg.type may be 'compaction_started'
// after
const SUPPORTED = new Set(['turn_started','message_started','thinking_started','response_delta','message_complete','thinking_complete','tool_call_started','tool_call_heartbeat','tool_call_complete','agent_spawned','agent_progress','agent_complete','approval_required','user_input_required','turn_complete','error']);
if (SUPPORTED.has(msg.type)) telemetry.observe({ event: msg.type, ...meta }, at); Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED = new Set(['turn_started','message_started','thinking_started','response_delta','message_complete','thinking_complete','tool_call_started','tool_call_heartbeat','tool_call_complete','agent_spawned','agent_progress','agent_complete','approval_required','user_input_required','turn_complete','error']);
if (SUPPORTED.has(msg.type)) telemetry.observe({ event: msg.type, ...project(meta) }, at); Type guard
const isSupportedEngineEvent = (e) => typeof e?.event === 'string' && SUPPORTED.has(e.event);
Try / catch
try {
telemetry.observe(meta, at);
} catch (err) {
if (err.message === 'Unsupported Engine pet event.') {
console.warn('ignoring unknown engine event', meta.event);
return;
}
throw err;
} Prevention
- Filter the raw event stream to lifecycle events before observing
- Map new protocol event kinds explicitly when the adapter is updated
- Keep a single SUPPORTED set shared by producers and tests
- Never forward raw log/event strings as e.event
When it happens
Trigger: Feeding raw EventMsg variants not in the adapter's switch (e.g. 'session_started', 'compaction_started', 'token_count', 'shutdown'); a new protocol event added upstream before the adapter learns it; typo'd event names like 'turn_start'; replaying a foreign telemetry tape with non-Engine event names.
Common situations: Protocol version drift: the Rust side added an event kind and the JS adapter is stale; a caller piping every session log event into observe instead of only lifecycle events; renaming an event in a refactor with one call site missed.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Archive the legacy recording before accepting more…
- Archive the legacy recording before accepting more…
- Archive the legacy recording before accepting more…
- Archive this pet recording before accepting more telemetry.
- Archive this pet recording before accepting more telemetry.
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/a278381f6855b044.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tui/pet_watch/pet-native.js:1823
start(key, 'agent', 'agent', id('id'));
else
this.pulse(key, at);
break;
}
case 'agent_complete':
finish(`agent:${id('id')}`);
break;
case 'approval_required':
case 'user_input_required':
this.waiting = this.add('human', 'human', at);
this.waiting.status = 'pending';
break;
case 'turn_complete':
this.active.clear();
this.waiting = undefined;
break;
case 'error': break;
default: throw new Error('Unsupported Engine pet event.');
}
// Receipt time is the error onset; never rewrite the operation's old start.
if (e.event === 'error' || e.failed === true)
this.add('error', 'error', at).status = 'error';
}
/** Waiting coverage comes from the existing typed shell's current request.
* It can extend a witnessed request, never invent one on a mid-turn attach. */
confirmWaiting(at, waiting) {
if (!waiting) {
this.waiting = undefined;
return;
}
if (this.waiting && at >= this.waiting.endTime)
this.waiting.endTime = at;
}
bucket(sequence) {
const end = (sequence + 1) * pet_telemetry_js_1.PET_BIN_MS;
const input = this.events.filter(e => e.startTime < end && e.endTime >= end - 12_400)View on GitHub (pinned to 73e0f67d83)