{"record":{"id":"19759313ad3c6896","repo":"BigPizzaV3/CodexPlusPlus","slug":"chat-completions","errorCode":null,"errorMessage":"当前中转未启用 Chat Completions 协议代理","messagePattern":"当前中转未启用 Chat Completions 协议代理","errorType":"http","errorClass":null,"httpStatus":502,"severity":"error","filePath":"crates/codex-plus-core/src/protocol_proxy.rs","lineNumber":872,"sourceCode":"    })\n}\n\nfn response_header_timeout(is_stream: bool) -> Duration {\n    if is_stream {\n        UPSTREAM_STREAM_HEADER_TIMEOUT\n    } else {\n        UPSTREAM_HEADER_TIMEOUT\n    }\n}\n\npub async fn open_chat_completions_proxy_request(\n    body: &str,\n    original_user_agent: Option<&str>,\n) -> anyhow::Result<UpstreamProxyResponse> {\n    let settings = SettingsStore::default().load().unwrap_or_default();\n    let relay = settings.active_relay_profile();\n    if relay.protocol != RelayProtocol::ChatCompletions {\n        anyhow::bail!(\"当前中转未启用 Chat Completions 协议代理\");\n    }\n    if relay.base_url.trim().is_empty() {\n        anyhow::bail!(\"Chat Completions 上游 Base URL 不能为空\");\n    }\n    if relay.api_key.trim().is_empty() {\n        anyhow::bail!(\"Chat Completions 上游 Key 不能为空\");\n    }\n\n    let request_json: Value = serde_json::from_str(body)?;\n    let is_stream = request_json\n        .get(\"stream\")\n        .and_then(Value::as_bool)\n        .unwrap_or(false);\n    let upstream = crate::http_client::proxied_client(&effective_user_agent(\n        &relay.user_agent,\n        original_user_agent,\n    ))?\n    .post(chat_completions_url(&relay.base_url))","sourceCodeStart":854,"sourceCodeEnd":890,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/1f431ae49b57b3055e0e6845ba6156c6b4232b4d/crates/codex-plus-core/src/protocol_proxy.rs#L854-L890","documentation":"Thrown by open_chat_completions_proxy_request in crates/codex-plus-core/src/protocol_proxy.rs when the chat completions proxy endpoint is called but the currently active relay profile's protocol is not RelayProtocol::ChatCompletions. The /chat/completions passthrough is only enabled for relays configured for the Chat Completions wire API; a Responses-protocol relay must use the responses proxy path instead.","triggerScenarios":"Client POSTs to the proxy's /v1/chat/completions path while the active provider profile is configured with protocol = Responses; user switched the active provider but the client kept calling the chat completions endpoint.","commonSituations":"Switching active provider from a chat-completions vendor to a responses vendor without updating the client's endpoint; test scripts hardcoded to /v1/chat/completions; profile misconfiguration where the user intended Chat Completions but left protocol as Responses.","solutions":["Switch the active relay profile's protocol to Chat Completions in the manager, or","Point the client at the responses proxy path (/v1/responses) if the active provider speaks the Responses API","Verify after any provider switch which wire API the new active profile uses before reusing old endpoint URLs"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let settings = SettingsStore::default().load().unwrap_or_default();\nif settings.active_relay_profile().protocol != RelayProtocol::ChatCompletions {\n    anyhow::bail!(\"active provider must use the Chat Completions protocol for this endpoint\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["After switching the active provider, confirm the client targets the endpoint matching its wire API","Surface the active protocol prominently in the UI so mismatches are obvious before requests are made"],"tags":["chat-completions","protocol-mismatch","relay-profile","proxy-endpoint"],"backgroundTag":"protocol-mismatch","analyzedSha":"1f431ae49b57b3055e0e6845ba6156c6b4232b4d","analyzedAt":"2026-08-16T20:54:18.598Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}