{"record":{"id":"5d027148db36192d","repo":"BigPizzaV3/CodexPlusPlus","slug":"codex-app-server-method-error","errorCode":null,"errorMessage":"Codex app-server {method} 失败：{error}","messagePattern":"Codex app-server (.+?) 失败：(.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/connect/app_server.rs","lineNumber":286,"sourceCode":"            \"params\": params\n        }))\n        .await?;\n        let deadline = tokio::time::Instant::now() + timeout;\n        loop {\n            let remaining = deadline.saturating_duration_since(tokio::time::Instant::now());\n            if remaining.is_zero() {\n                bail!(\"Codex app-server {method} 请求超时\");\n            }\n            let message = self.read_message(remaining).await?;\n            if is_server_request(&message) {\n                self.reject_server_request(&message).await?;\n                continue;\n            }\n            if response_id(&message) != Some(id) {\n                continue;\n            }\n            if let Some(error) = rpc_error(&message) {\n                bail!(\"Codex app-server {method} 失败：{error}\");\n            }\n            return Ok(message.get(\"result\").cloned().unwrap_or(Value::Null));\n        }\n    }\n\n    async fn read_message(&mut self, timeout: Duration) -> anyhow::Result<Value> {\n        loop {\n            let line = tokio::time::timeout(timeout, self.stdout.next_line())\n                .await\n                .context(\"等待 Codex app-server 响应超时\")??;\n            let Some(line) = line else {\n                self.running = false;\n                let exit = self.child.try_wait().ok().flatten();\n                bail!(\n                    \"Codex app-server 已关闭{}\",\n                    exit.map(|status| format!(\"：{status}\")).unwrap_or_default()\n                );\n            };","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/f2074595a281bc057525c748175c8eb9805b0673/crates/codex-plus-core/src/connect/app_server.rs#L268-L304","documentation":"The JSON-RPC response to initialize, thread/start or thread/resume carried an error object; request() rethrows its message with the method name prefixed. Typical causes are an invalid or expired threadId on thread/resume, or an initialize payload the installed app-server rejects.","triggerScenarios":"prepare_thread(Some(id)) where the saved thread was deleted or belongs to another codex version; initialize capabilities object rejected after an app-server protocol change.","commonSituations":"Session files persisted across a codex upgrade; thread rolled by retention; version skew between codex-plus-core and the codex CLI.","solutions":["Drop the stored thread id and retry with thread/start, the connector already implements this fallback for resume failures","Read the appended error text to find the offending field","Align codex-plus-core with the installed codex app-server version","Clear stale connect-session state for the account if resume keeps failing"],"exampleFix":"// before\nlet thread_id = server.prepare_thread(saved.as_deref()).await?;\n// after: resume failure falls back to a new thread, as the connector does\nlet thread_id = match server.prepare_thread(saved.as_deref()).await {\n    Ok(id) => id,\n    Err(_) => server.prepare_thread(None).await?,\n};","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"let thread_id = match server.prepare_thread(saved.as_deref()).await {\n    Ok(id) => id,\n    Err(_) => server.prepare_thread(None).await?,\n};","preventionTips":["Always pair thread/resume with a thread/start fallback","Clear persisted thread ids after codex upgrades","Log the method-prefixed error text to identify the rejected field"],"tags":["jsonrpc","codex","rpc-error","thread"],"backgroundTag":"jsonrpc-error-response","analyzedSha":"f2074595a281bc057525c748175c8eb9805b0673","analyzedAt":"2026-08-23T12:52:24.489Z","contentChangedAt":"2026-08-23T12:52:24.489Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}