{"record":{"id":"22b22802c5db2eda","repo":"Hmbown/CodeWhale","slug":"runtime-eventname-is-missing-its-request-identity-codewhale","errorCode":null,"errorMessage":"Runtime ${eventName} is missing its request identity.","messagePattern":"Runtime (.+?) is missing its request identity\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/src/core/codewhale.ts","lineNumber":450,"sourceCode":"          startTime: start, endTime: Math.max(start, end), openEnded: eventName !== 'turn.completed',\n          agentId, name: 'turn', category: 'orchestration', model,\n          inputTokens: num(usage.input_tokens), outputTokens: num(usage.output_tokens),\n          status: statusOf(turn.status ?? payload.status), latency: num(turn.duration_ms),\n          attributes: { 'codewhale.seq': rec.seq, 'codewhale.turn_id': turnId, 'whalesong.container': true,\n            ...(statusOf(turn.status ?? payload.status) === 'error' ? { 'whalesong.error_onset_ms': relative } : {}) },\n          payload: { input_summary: clip(turn.input_summary) }, raw: rec,\n        };\n        if (existing >= 0) {\n          const prior = events[existing]!; this.measure(prior, { ...next, startTime: prior.startTime });\n        }\n        else this.push(next);\n        continue;\n      }\n      if (eventName === 'turn.lifecycle') continue;\n      if (['approval.required', 'approval.decided', 'approval.timeout', 'user_input.required', 'user_input.answered', 'user_input.canceled'].includes(eventName)) {\n        const kind = eventName.startsWith('approval.') ? 'approval' : 'user_input';\n        const requestId = str(payload[kind === 'approval' ? 'approval_id' : 'input_id']) ?? str(payload.id);\n        if (!requestId) throw new Error(`Runtime ${eventName} is missing its request identity.`);\n        const key = JSON.stringify([turnId ?? '', kind, requestId]);\n        const prior = requests.get(key), required = eventName.endsWith('.required');\n        if (required && prior) continue;\n        if (!required && prior) {\n          const next: WhaleEvent = { ...prior, attributes: { ...prior.attributes },\n            endTime: Math.max(prior.startTime, relative), openEnded: false,\n            status: eventName === 'approval.decided' || eventName === 'user_input.answered' ? 'success' : 'unknown' };\n          if (payload.auto === true) {\n            // Automatic consent has a receipt, but never asked the human to wait.\n            next.category = 'orchestration'; delete next.attributes['whalesong.waiting'];\n            next.attributes['whalesong.container'] = true;\n          }\n          this.measure(prior, next); requests.delete(key); continue;\n        }\n        const automatic = payload.auto === true;\n        const event: WhaleEvent = {\n          schemaVersion: 1, id: `request:${key}:${rec.seq}`, traceId: threadId,\n          parentId: turnId ? `turn:${turnId}` : undefined, startTime: relative, endTime: relative,","sourceCodeStart":432,"sourceCodeEnd":468,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/src/core/codewhale.ts#L432-L468","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n{ \"event\": \"approval.decided\", \"payload\": { \"turn_id\": \"t1\", \"decision\": \"allow\" } }\n// after\n{ \"event\": \"approval.decided\", \"payload\": { \"turn_id\": \"t1\", \"approval_id\": \"apr_42\", \"decision\": \"allow\" } }","handlingStrategy":"validation","validationCode":"function hasRequestId(rec) {\n  const ev = rec?.event ?? '';\n  if (!/^(approval|user_input)\\./.test(ev)) return true;\n  const kind = ev.startsWith('approval.') ? 'approval' : 'user_input';\n  const p = rec.payload ?? {};\n  return typeof (p[kind === 'approval' ? 'approval_id' : 'input_id'] ?? p.id) === 'string';\n}","typeGuard":"const hasRequestIdentity = (p) => typeof (p?.approval_id ?? p?.input_id ?? p?.id) === 'string' && (p?.approval_id ?? p?.input_id ?? p?.id).length > 0;","tryCatchPattern":"try {\n  const trace = fromCodewhaleRuntime(records);\n} catch (e) {\n  if (e.message.includes('missing its request identity')) {\n    console.error('approval/user_input event without id; re-export from a v2 runtime');\n  } else throw e;\n}","preventionTips":["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."],"tags":["import","validation","codewhale","request-identity"],"backgroundTag":"schema-validation-failed","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}