BigPizzaV3/CodexPlusPlus · error

Chat Completions 上游 Base URL 不能为空

Error message

Chat Completions 上游 Base URL 不能为空

What it means

Thrown by open_chat_completions_proxy_request in crates/codex-plus-core/src/protocol_proxy.rs when the active relay profile is configured for the Chat Completions protocol but its base_url field is empty (or whitespace-only). Without a base URL the proxy cannot construct the upstream chat completions URL, so it aborts before sending anything.

Source

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

fn response_header_timeout(is_stream: bool) -> Duration {
    if is_stream {
        UPSTREAM_STREAM_HEADER_TIMEOUT
    } 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)

View on GitHub (pinned to 1f431ae49b)

Solutions

  1. Open the active provider profile and fill in the upstream Base URL (e.g. https://api.vendor.com)
  2. Ensure trailing slashes are fine (they are trimmed) but the URL must be non-empty and should include scheme and host
  3. If importing from a share link, include the baseUrl query parameter
Defensive patterns

Strategy: validation

Validate before calling

fn chat_relay_ready(relay: &RelayProfile) -> bool {
    relay.protocol == RelayProtocol::ChatCompletions && !relay.base_url.trim().is_empty()
}

Prevention

When it happens

Trigger: Calling the chat completions proxy with an active ChatCompletions profile whose base_url was never filled in or was cleared; importing a provider definition that omitted baseUrl; settings file edited by hand leaving an empty string.

Common situations: Newly created provider profile saved before entering the endpoint; profile import from URL/query missing the baseUrl parameter; user cleared the field intending to switch providers later but the profile stayed active.

Related errors


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