BigPizzaV3/CodexPlusPlus · error

中转 Base URL 不能为空

Error message

中转 Base URL 不能为空

What it means

Thrown by `apply_relay_config_to_home_with_session_provider` in relay_config.rs when the `base_url` argument is empty after trimming. This function writes the relay provider entry into the codex home config.toml; without a base URL the generated `model_provider` would have no endpoint, so the apply aborts before touching files. It is the first validation in the apply pipeline.

Solutions

  1. Pass the relay endpoint (e.g. "https://relay.example.com") as base_url.
  2. Load and validate the saved profile before applying; reject blank base_url in the UI.
  3. If a default endpoint exists for the protocol, substitute it before calling the apply function.

Example fix

// before
apply_relay_config_to_home_with_protocol(home, "", key, protocol, port, sp).await?;
// after
apply_relay_config_to_home_with_protocol(home, "https://relay.example.com", key, protocol, port, sp).await?;
Defensive patterns

Strategy: validation

Validate before calling

let base_url = base_url.trim();
anyhow::ensure!(!base_url.is_empty(), "中转 Base URL 不能为空");
anyhow::ensure!(base_url.starts_with("http"), "中转 Base URL 必须是 http(s) URL");

Type guard

fn valid_base_url(url: &str) -> bool {
    let u = url.trim(); u.starts_with("http://") || u.starts_with("https://")
}

Try / catch

match apply_relay_config_to_home_with_protocol(home, url, key, proto, port, sp).await {
    Ok(r) => info!("applied: {:?}", r),
    Err(e) if e.to_string().contains("中转 Base URL 不能为空") => warn!("profile missing endpoint; skipping apply"),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `apply_relay_config_to_home_with_protocol` / `apply_relay_config_to_home_with_session_provider` with `base_url = ""` or `" "`; bails at relay_config.rs:401 before bearer-token and session-provider checks.

Common situations: A relay profile was saved without an endpoint; a UI passed an empty string because the profile field was never filled; refactoring code that previously defaulted the URL now passes an empty value.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19). Data as JSON: /api/errors/1da5718ff11cb388. Report an issue: GitHub.

Appendix: source

Thrown at crates/codex-plus-core/src/relay_config.rs:401

        base_url,
        bearer_token,
        protocol,
        proxy_port,
        RelaySessionProvider::Custom,
    )
}

pub fn apply_relay_config_to_home_with_session_provider(
    home: &Path,
    base_url: &str,
    bearer_token: &str,
    protocol: RelayProtocol,
    proxy_port: u16,
    session_provider: RelaySessionProvider,
) -> anyhow::Result<RelayApplyResult> {
    let base_url = base_url.trim();
    if base_url.is_empty() {
        anyhow::bail!("中转 Base URL 不能为空");
    }
    let bearer_token = bearer_token.trim();
    if bearer_token.is_empty() {
        anyhow::bail!("中转 Key 不能为空");
    }
    if session_provider == RelaySessionProvider::Openai && protocol != RelayProtocol::Responses {
        anyhow::bail!("OpenAI 会话身份仅支持 Responses API");
    }
    let codex_base_url = codex_base_url_for_protocol(base_url, protocol, proxy_port);
    let updated = upsert_model_provider_config_with_session_provider(
        "",
        &codex_base_url,
        bearer_token,
        true,
        session_provider,
    )?;
    let auth_contents = serde_json::to_string_pretty(&json!({
        "OPENAI_API_KEY": bearer_token

View on GitHub (pinned to b1ed92e5e4)