{"record":{"id":"71814105198550e5","repo":"Hmbown/CodeWhale","slug":"serialize-runtime-event-envelope","errorCode":null,"errorMessage":"serialize runtime event envelope","messagePattern":"serialize runtime event envelope","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_api.rs","lineNumber":5898,"sourceCode":"\nfn runtime_event_payload(event: crate::runtime_threads::RuntimeEventRecord) -> serde_json::Value {\n    let event_name = event.event.clone();\n    let timestamp = event.timestamp.to_rfc3339();\n    let schema_version = RUNTIME_EVENT_ENVELOPE_SCHEMA_VERSION;\n    let envelope = RuntimeEventEnvelope {\n        schema_version,\n        seq: event.seq,\n        event: event_name.clone(),\n        kind: event_name,\n        thread_id: event.thread_id,\n        turn_id: event.turn_id,\n        item_id: event.item_id,\n        timestamp: timestamp.clone(),\n        created_at: Some(timestamp),\n        payload: event.payload,\n        extra: Default::default(),\n    };\n    serde_json::to_value(envelope).expect(\"serialize runtime event envelope\")\n}\n\nfn runtime_event_payload_with_previous(\n    event: crate::runtime_threads::RuntimeEventRecord,\n    previous_seq: u64,\n) -> serde_json::Value {\n    let mut payload = runtime_event_payload(event);\n    if let Some(object) = payload.as_object_mut() {\n        object.insert(\"previous_seq\".to_string(), json!(previous_seq));\n    }\n    payload\n}\n\nfn map_compat_stream_event(event: &crate::runtime_threads::RuntimeEventRecord) -> Option<SseEvent> {\n    let payload = &event.payload;\n    match event.event.as_str() {\n        \"item.delta\" => {\n            let kind = payload","sourceCodeStart":5880,"sourceCodeEnd":5916,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/runtime_api.rs#L5880-L5916","documentation":"This `expect` panics when `serde_json::to_value(envelope)` fails to serialize a `RuntimeEventRecord` into a JSON `Value`. The library authors treat runtime event envelopes as trivially serializable, so any serialization failure is considered a programmer bug rather than a recoverable runtime condition. It is thrown in `runtime_api.rs` while building the JSON payload for a runtime event.","triggerScenarios":"Calling the runtime event envelope builder in crates/tui/src/runtime_api.rs:5898 when `event.payload` (or another envelope field like `timestamp`/`created_at`) contains a type whose `Serialize` implementation fails — e.g. a non-string map key unsupported by serde_json or a serializer error from a custom Serialize impl on the payload.","commonSituations":"Adding a new field or payload variant to `RuntimeEventRecord` whose serde_json serialization fails (e.g. heterogeneous map keys, unserializable nested types); swapping the payload type to a custom serde type that errors at runtime.","solutions":["Inspect the failing payload variant: run with a backtrace (RUST_BACKTRACE=1) and identify which field of `RuntimeEventRecord` fails to serialize.","Ensure all fields use JSON-compatible types (map keys must be strings or string-like; avoid `serde_json::Value` objects with non-string keys).","Replace the `expect` with a `Result` return and propagate the serialization error to the caller.","Add a serialization round-trip test for the new payload variant."],"exampleFix":"// before\nserde_json::to_value(envelope).expect(\"serialize runtime event envelope\")\n// after\nserde_json::to_value(&envelope)\n    .map_err(|e| ToolError::execution_failed(format!(\"serialize runtime event envelope: {e}\")))?","handlingStrategy":"try-catch","validationCode":"// Caller-side: ensure the payload round-trips before handing it to the runtime\nfn ensure_json_serializable<T: serde::Serialize>(v: &T) -> Result<(), serde_json::Error> {\n    serde_json::to_value(v).map(|_| ())\n}","typeGuard":"fn is_json_safe(v: &serde_json::Value) -> bool {\n    match v {\n        serde_json::Value::Object(m) => m.iter().all(|(k, x)| is_json_safe(x)),\n        serde_json::Value::Array(a) => a.iter().all(is_json_safe),\n        _ => true,\n    }\n}","tryCatchPattern":"// Rust: replace expect with explicit error propagation\nlet value = serde_json::to_value(&envelope)\n    .map_err(|e| ToolError::execution_failed(format!(\"envelope serialization failed: {e}\")))?;","preventionTips":["Keep envelope fields JSON-compatible (string map keys, plain types).","Add a round-trip serialization test for every new RuntimeEventRecord payload variant.","Prefer Result-returning serialization at API boundaries over expect/unwrap.","Run with RUST_BACKTRACE=1 in CI so panics locate the offending field quickly."],"tags":["serde","json","serialization","panic"],"backgroundTag":"json-marshal-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"}