Hmbown/CodeWhale · error · Error
Runtime is missing its request identity.
Error message
Runtime ${eventName} is missing its request identity. What it means
Approval and user-input lifecycle events in a Codewhale runtime stream must carry a request identifier (approval_id/input_id, or a generic id). Without it the journal cannot correlate the request with its later decision/answer/timeout, so the library rejects the event instead of building an unmatchable entry.
Solutions
- Inspect the failing event's payload and ensure it includes approval_id (for approval.*) or input_id (for user_input.*) — payload.id is accepted as a fallback.
- Re-export the runtime file from a runtime version that emits request identities (runtime-events/v2).
- If events were post-processed, restore the id field instead of stripping it.
- Check the runtime source that emits these events and add the identifier there if it is genuinely missing.
Example fix
// before
{ "event": "approval.decided", "payload": { "turn_id": "t1", "decision": "allow" } }
// after
{ "event": "approval.decided", "payload": { "turn_id": "t1", "approval_id": "apr_42", "decision": "allow" } } Defensive patterns
Strategy: validation
Validate before calling
function hasRequestId(rec) {
const ev = rec?.event ?? '';
if (!/^(approval|user_input)\./.test(ev)) return true;
const kind = ev.startsWith('approval.') ? 'approval' : 'user_input';
const p = rec.payload ?? {};
return typeof (p[kind === 'approval' ? 'approval_id' : 'input_id'] ?? p.id) === 'string';
} Type guard
const hasRequestIdentity = (p) => typeof (p?.approval_id ?? p?.input_id ?? p?.id) === 'string' && (p?.approval_id ?? p?.input_id ?? p?.id).length > 0;
Try / catch
try {
const trace = fromCodewhaleRuntime(records);
} catch (e) {
if (e.message.includes('missing its request identity')) {
console.error('approval/user_input event without id; re-export from a v2 runtime');
} else throw e;
} Prevention
- Never redact or strip *_id fields when post-processing runtime event files.
- Pin the runtime/exporter to a version that emits runtime-events/v2 with request identities.
- Pre-scan approval.*/user_input.* records for approval_id/input_id/id before import.
- When hand-crafting events, always copy the approval_id/input_id from the originating request.
When it happens
Trigger: Importing a runtime events file where an approval.required / approval.decided / approval.timeout / user_input.required / user_input.answered / user_input.canceled record's payload lacks both the kind-specific id field and a fallback payload.id.
Common situations: A runtime version or exporter that renamed or dropped the id field; hand-edited or redacted event payloads; a custom event emitter emitting approval/user_input events without the identifier; older event format (not runtime-events/v2) fed to this importer.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Codewhale runtime event file is empty.
- Runtime import contains multiple threads. Export one thread…
- bundle contains conflicting or rejected entries
- Choose one recording to import.
- Codewhale runtime file contained only stream deltas or…
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/22b22802c5db2eda.
Report an issue: GitHub.
Appendix: source
Thrown at pet/src/core/codewhale.ts:450
startTime: start, endTime: Math.max(start, end), openEnded: eventName !== 'turn.completed',
agentId, name: 'turn', category: 'orchestration', model,
inputTokens: num(usage.input_tokens), outputTokens: num(usage.output_tokens),
status: statusOf(turn.status ?? payload.status), latency: num(turn.duration_ms),
attributes: { 'codewhale.seq': rec.seq, 'codewhale.turn_id': turnId, 'whalesong.container': true,
...(statusOf(turn.status ?? payload.status) === 'error' ? { 'whalesong.error_onset_ms': relative } : {}) },
payload: { input_summary: clip(turn.input_summary) }, raw: rec,
};
if (existing >= 0) {
const prior = events[existing]!; this.measure(prior, { ...next, startTime: prior.startTime });
}
else this.push(next);
continue;
}
if (eventName === 'turn.lifecycle') continue;
if (['approval.required', 'approval.decided', 'approval.timeout', 'user_input.required', 'user_input.answered', 'user_input.canceled'].includes(eventName)) {
const kind = eventName.startsWith('approval.') ? 'approval' : 'user_input';
const requestId = str(payload[kind === 'approval' ? 'approval_id' : 'input_id']) ?? str(payload.id);
if (!requestId) throw new Error(`Runtime ${eventName} is missing its request identity.`);
const key = JSON.stringify([turnId ?? '', kind, requestId]);
const prior = requests.get(key), required = eventName.endsWith('.required');
if (required && prior) continue;
if (!required && prior) {
const next: WhaleEvent = { ...prior, attributes: { ...prior.attributes },
endTime: Math.max(prior.startTime, relative), openEnded: false,
status: eventName === 'approval.decided' || eventName === 'user_input.answered' ? 'success' : 'unknown' };
if (payload.auto === true) {
// Automatic consent has a receipt, but never asked the human to wait.
next.category = 'orchestration'; delete next.attributes['whalesong.waiting'];
next.attributes['whalesong.container'] = true;
}
this.measure(prior, next); requests.delete(key); continue;
}
const automatic = payload.auto === true;
const event: WhaleEvent = {
schemaVersion: 1, id: `request:${key}:${rec.seq}`, traceId: threadId,
parentId: turnId ? `turn:${turnId}` : undefined, startTime: relative, endTime: relative,View on GitHub (pinned to 433685b202)