{"record":{"id":"07cfc2a05c8a4081","repo":"BigPizzaV3/CodexPlusPlus","slug":"key-protocol-proxy","errorCode":null,"errorMessage":"图片上游 Key 不能为空","messagePattern":"图片上游 Key 不能为空","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/protocol_proxy.rs","lineNumber":995,"sourceCode":"    content_type: &str,\n    original_user_agent: Option<&str>,\n    endpoint_kind: ImageProxyEndpoint,\n) -> anyhow::Result<UpstreamProxyResponse> {\n    let settings = SettingsStore::default().load().unwrap_or_default();\n    let relay = crate::relay_rotation::select_relay_for_probe(&settings)?;\n    let base_url = if relay.upstream_base_url.trim().is_empty() {\n        crate::relay_config::relay_profile_base_url(&relay)\n    } else {\n        relay.upstream_base_url.trim().to_string()\n    };\n    if is_local_protocol_proxy_base_url(&base_url) {\n        anyhow::bail!(\"图片上游 Base URL 不能指向本地协议代理\");\n    }\n    if base_url.trim().is_empty() {\n        anyhow::bail!(\"图片上游 Base URL 不能为空\");\n    }\n    if relay.api_key.trim().is_empty() && !relay.uses_no_auth() {\n        anyhow::bail!(\"图片上游 Key 不能为空\");\n    }\n    let content_type = content_type.trim();\n    let content_type = if content_type.is_empty() {\n        match endpoint_kind {\n            ImageProxyEndpoint::Generations => \"application/json\",\n            ImageProxyEndpoint::Edits => {\n                anyhow::bail!(\"图片 edits 请求缺少 Content-Type\");\n            }\n        }\n    } else {\n        content_type\n    };\n    let endpoint = endpoint_kind.url(&base_url);\n    let wire_api = endpoint_kind.wire_api();\n    let _ = crate::diagnostic_log::append_diagnostic_log(\n        \"protocol_proxy.image_request\",\n        json!({\n            \"relayId\": relay.id,","sourceCodeStart":977,"sourceCodeEnd":1013,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/crates/codex-plus-core/src/protocol_proxy.rs#L977-L1013","documentation":"open_image_proxy_request requires an upstream API key for image API requests unless the relay profile is explicitly configured with no-auth mode. It bails when api_key is empty/whitespace and uses_no_auth() is false. This ensures the upstream image API call carries credentials.","triggerScenarios":"Calling open_image_generations_proxy_request or open_image_edits_proxy_request with the active relay profile's api_key blank and uses_no_auth() not enabled.","commonSituations":"New profile created without pasting the upstream API key; key removed during profile edit; using a paid image API that requires auth while profile was copied from a no-auth local setup.","solutions":["Set the 图片上游 Key (api_key) in the active relay profile","If the upstream genuinely needs no key, enable the profile's no-auth option so uses_no_auth() returns true","Re-apply the profile and retry the image request"],"exampleFix":"// before\napi_key = \"\"\n// after\napi_key = \"sk-...\"","handlingStrategy":"validation","validationCode":"if relay.api_key.trim().is_empty() && !relay.uses_no_auth() { return Err(\"upstream api key missing\"); }","typeGuard":null,"tryCatchPattern":"match open_image_generations_proxy_request(...) {\n    Err(e) if e.to_string().contains(\"Key 不能为空\") => eprintln!(\"请在当前中转填写图片上游 Key: {e}\"),\n    other => other?,\n}","preventionTips":["Enter the API key when creating the profile","Enable no-auth explicitly only for keyless upstreams","Rotate/verify the key after profile edits"],"tags":["config","validation","api-key","auth"],"backgroundTag":"missing-api-key","analyzedSha":"b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6","analyzedAt":"2026-09-19T23:35:21.129Z","contentChangedAt":"2026-09-19T23:35:21.129Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}