{"record":{"id":"7c031741d7ab33c8","repo":"BigPizzaV3/CodexPlusPlus","slug":"error-7c0317","errorCode":null,"errorMessage":"{error}","messagePattern":"\\{error\\}","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/connect/app_server.rs","lineNumber":192,"sourceCode":"                usage = reported_usage;\n            }\n\n            match message.get(\"method\").and_then(Value::as_str) {\n                Some(\"item/completed\") => {\n                    if let Some(text) = extract_completed_agent_text(&message) {\n                        if !reply_parts.iter().any(|part| part == &text) {\n                            reply_parts.push(text);\n                        }\n                    }\n                }\n                Some(\"turn/completed\") => turn_completed = true,\n                Some(\"thread/status/changed\") if thread_status_is_idle(&message) => {\n                    turn_completed = true;\n                }\n                Some(\"error\") => {\n                    let error = deep_string(message.get(\"params\"), &[\"message\", \"error\"])\n                        .unwrap_or_else(|| \"Codex app-server 返回未知错误\".to_string());\n                    bail!(\"{error}\");\n                }\n                _ => {}\n            }\n        }\n        Ok(AppServerTurnResult {\n            reply: reply_parts.join(\"\\n\\n\"),\n            model,\n            usage,\n        })\n    }\n\n    pub async fn close(&mut self) {\n        self.running = false;\n        let _ = self.stdin.shutdown().await;\n        let _ = self.child.start_kill();\n        let _ = self.child.wait().await;\n    }\n","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/f2074595a281bc057525c748175c8eb9805b0673/crates/codex-plus-core/src/connect/app_server.rs#L174-L210","documentation":"While the turn was streaming, the app-server pushed a JSON-RPC notification with method error; run_turn extracts params.message or params.error and bails with that text, falling back to a generic unknown-error string when neither field is present. This is a mid-turn failure from the Codex side, surfaced to the caller as the turn error.","triggerScenarios":"run_turn receives an error notification before turn/completed: upstream model provider failure, rate limit, expired codex auth, or an app-server internal error.","commonSituations":"Quota exhausted mid-generation on the provider or relay; codex login token expired during a long turn; transient provider 5xx.","solutions":["Read the forwarded message, it is the server-side reason such as quota, auth, or provider error","Re-authenticate with codex login when the text mentions auth or token","Retry the turn after a short backoff for transient provider errors","Check relay profile quota and model availability when using a relay"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"let reply = match server.run_turn(&thread_id, prompt).await {\n    Ok(r) => r,\n    Err(e) => {\n        log_error(&e);\n        tokio::time::sleep(Duration::from_secs(3)).await;\n        server.run_turn(&thread_id, prompt).await?\n    }\n};","preventionTips":["Monitor provider quota and relay limits before they hit mid-turn","Keep codex auth fresh, re-login on any auth-worded error","Cap retry count so a persistent server error surfaces to the user"],"tags":["codex","server-error","notification","turn"],"backgroundTag":"server-error-notification","analyzedSha":"f2074595a281bc057525c748175c8eb9805b0673","analyzedAt":"2026-08-23T12:52:24.489Z","contentChangedAt":"2026-08-23T12:52:24.489Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}