BigPizzaV3/CodexPlusPlus · error

Chat Completions 上游 Key 不能为空

Error message

Chat Completions 上游 Key 不能为空

What it means

Thrown by open_chat_completions_proxy_request in crates/codex-plus-core/src/protocol_proxy.rs when the active Chat Completions relay profile has an empty api_key. The proxy authenticates upstream with bearer_auth(relay.api_key), and it refuses to send an anonymous request rather than failing upstream with a 401.

Source

Thrown at crates/codex-plus-core/src/protocol_proxy.rs:878

    } 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() {
        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 upstream = crate::http_client::proxied_client(&effective_user_agent(
        &relay.user_agent,
        original_user_agent,
    ))?
    .post(chat_completions_url(&relay.base_url))
    .bearer_auth(relay.api_key.trim())
    .header(reqwest::header::CONTENT_TYPE, "application/json")
    .json(&request_json)
    .send()
    .await?;
    let status_code = upstream.status().as_u16();

View on GitHub (pinned to 1f431ae49b)

Solutions

  1. Enter the upstream API key in the active provider profile and save
  2. If the key was intentionally left blank for a local gateway that needs no auth, note this proxy still requires a non-empty value — put any placeholder only if your gateway accepts it
  3. Re-import the provider with the apiKey parameter included
Defensive patterns

Strategy: validation

Validate before calling

fn relay_has_key(relay: &RelayProfile) -> bool {
    !relay.api_key.trim().is_empty()
}

Prevention

When it happens

Trigger: Chat completions proxy request while the active profile's api_key is blank; provider import that carried an empty apiKey; key field cleared during rotation to a vendor that was never configured.

Common situations: Half-configured provider left active; imported share link missing the apiKey parameter; user rotated keys and saved the profile before pasting the new key.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16). Data as JSON: /api/errors/d6e77259b08df444. Report an issue: GitHub.