{"record":{"id":"363a490a62257234","repo":"Hmbown/CodeWhale","slug":"runtime-api-turn-response-missing-turn-id","errorCode":null,"errorMessage":"runtime API turn response missing turn.id","messagePattern":"runtime API turn response missing turn\\.id","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/app-server/src/lib.rs","lineNumber":1180,"sourceCode":"        &mut self,\n        thread_id: &str,\n        input: &str,\n        writer: &mut W,\n        registration: Option<(TurnRegistry, String)>,\n    ) -> Result<Value> {\n        let turn = self\n            .request_json(\n                self.authed(\n                    self.client\n                        .post(format!(\"{}/v1/threads/{thread_id}/turns\", self.base_url)),\n                )\n                .json(&json!({ \"prompt\": input })),\n            )\n            .await?;\n        let turn_id = turn\n            .pointer(\"/turn/id\")\n            .and_then(Value::as_str)\n            .ok_or_else(|| anyhow!(\"runtime API turn response missing turn.id\"))?\n            .to_string();\n        let response_id = format!(\"{thread_id}:{turn_id}\");\n\n        emit_stdio_event(\n            writer,\n            json!({\n                \"type\": \"response_start\",\n                \"response_id\": response_id,\n            }),\n        )\n        .await?;\n\n        // Publish the turn only for the streaming window, and take it back\n        // before any `?` below: a turn that has already finished must never\n        // look cancellable.\n        if let Some((registry, key)) = registration.as_ref() {\n            registry.lock().await.insert(\n                key.clone(),","sourceCodeStart":1162,"sourceCodeEnd":1198,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/app-server/src/lib.rs#L1162-L1198","documentation":"Contract guard on the runtime API's turn creation response: the JSON accepted for a POST to /v1/threads/{thread_id}/turns is missing the /turn/id string field. Without a turn id the subsequent event stream cannot be correlated, so the malformed response is rejected rather than guessed at. The faulty input is the runtime's turn JSON.","triggerScenarios":"Thrown at crates/app-server/src/lib.rs:1180 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Retry the turn; a truncated or malformed response can be transient","Verify the runtime bridge version matches the app server (an older runtime may omit turn.id)","Inspect the runtime's response via logs to confirm the turn object shape","Restart or upgrade the runtime bridge if it consistently omits turn ids"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}