BigPizzaV3/CodexPlusPlus · error
Chat Completions 上游 Key 不能为空
Error message
Chat Completions 上游 Key 不能为空
What it means
The Chat Completions proxy requires an upstream API key unless the profile is in no-auth mode. It bails when relay.api_key is empty/whitespace and uses_no_auth() is false, so the forwarded request always carries credentials when the upstream expects them.
Solutions
- Set the Chat Completions 上游 Key (api_key) in the active relay profile
- Enable the profile's no-auth option if the upstream truly needs no key
- Re-apply the profile and retry
Example fix
// before api_key = "" // after api_key = "sk-..."
Defensive patterns
Strategy: validation
Validate before calling
if relay.api_key.trim().is_empty() && !relay.uses_no_auth() { return Err("chat completions upstream api key missing"); } Try / catch
match proxy_chat_completions(...) {
Err(e) if e.to_string().contains("Key 不能为空") => eprintln!("请填写 Chat Completions 上游 Key: {e}"),
other => other?,
} Prevention
- Enter the key when creating chat_completions profiles
- Use no-auth mode only for keyless upstreams
- Verify key presence after each profile edit
When it happens
Trigger: Chat Completions proxy request arrives with active_relay_profile().api_key blank and uses_no_auth() false.
Common situations: New Chat Completions profile without a key; key removed during edit; copying a local no-auth profile to point at a real paid upstream.
Understand the failure class
Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.
Related errors
- 上游 Key 不能为空
- 图片上游 Key 不能为空
- 官方混合 API 不应在 auth.json 中保存 OPENAI_API_KEY。请清理此供应商的…
- API Key 不能为空
- 请在设置中填写有效 API Key
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/d6e77259b08df444.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/protocol_proxy.rs:1071
} else {
UPSTREAM_HEADER_TIMEOUT
}
}
pub async fn open_chat_completions_proxy_request(
body: &str,
original_user_agent: Option<&str>,
) -> anyhow::Result<UpstreamProxyResponse> {
let settings = SettingsStore::default().load().unwrap_or_default();
let relay = settings.active_relay_profile();
if relay.protocol != RelayProtocol::ChatCompletions {
anyhow::bail!("当前中转未启用 Chat Completions 协议代理");
}
if relay.base_url.trim().is_empty() {
anyhow::bail!("Chat Completions 上游 Base URL 不能为空");
}
if relay.api_key.trim().is_empty() && !relay.uses_no_auth() {
anyhow::bail!("Chat Completions 上游 Key 不能为空");
}
let request_json: Value = serde_json::from_str(body)?;
let is_stream = request_json
.get("stream")
.and_then(Value::as_bool)
.unwrap_or(false);
let request = crate::http_client::proxied_client(&effective_user_agent(
&relay.user_agent,
original_user_agent,
))?
.post(chat_completions_url(&relay.base_url))
.header(reqwest::header::CONTENT_TYPE, "application/json")
.json(&request_json);
let upstream = with_relay_auth(request, &relay).send().await?;
let status_code = upstream.status().as_u16();
let content_type = upstream
.headers()View on GitHub (pinned to b1ed92e5e4)