BigPizzaV3/CodexPlusPlus · error

官方混合 API 不应在 auth.json 中保存 OPENAI_API_KEY。请清理此供应商的…

Error message

官方混合 API 不应在 auth.json 中保存 OPENAI_API_KEY。请清理此供应商的 auth.json 后再切换。

What it means

For profiles configured as official hybrid API (官方混合 API), validate_switch_profile_files checks the profile's auth.json contents and fails the switch if an OPENAI_API_KEY entry is present and non-empty. Hybrid-mode auth must come from ChatGPT login tokens, not a stored API key.

Solutions

  1. Remove the OPENAI_API_KEY field (or empty its value) from this provider's auth.json, then retry the switch
  2. If the provider actually uses API-key auth, change relay_mode away from the official hybrid API mode

Example fix

// before
{ "OPENAI_API_KEY": "sk-...", "tokens": null }
// after
{ "OPENAI_API_KEY": "", "tokens": null }
Defensive patterns

Strategy: validation

Validate before calling

fn hybrid_auth_ok(auth_json: &str) -> bool {
    serde_json::from_str::<serde_json::Value>(auth_json)
        .ok()
        .and_then(|v| v.get("OPENAI_API_KEY").and_then(serde_json::Value::as_str).map(str::trim).map(|s| s.is_empty()))
        .unwrap_or(true)
}

Try / catch

match apply_selected_relay_profile(&profile) {
    Err(e) if e.to_string().contains("官方混合 API") => {
        clean_openai_api_key_from_auth(&mut profile);
        retry(profile)
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling apply_selected_relay_profile on a hybrid-API profile whose auth_contents JSON contains OPENAI_API_KEY set to a non-empty string.

Common situations: User pasted an auth.json exported from an API-key-based provider into a hybrid profile; profile was converted from API-key mode to hybrid mode without cleaning auth.json.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at crates/codex-plus-core/src/relay_switch.rs:185

                profile.id.as_str()
            } else {
                profile.name.as_str()
            }
        );
    }
    if profile.relay_mode == RelayMode::Official
        && serde_json::from_str::<serde_json::Value>(&profile.auth_contents)
            .ok()
            .and_then(|value| {
                value
                    .get("OPENAI_API_KEY")
                    .and_then(serde_json::Value::as_str)
                    .map(str::trim)
                    .map(str::is_empty)
            })
            == Some(false)
    {
        anyhow::bail!(
            "官方混合 API 不应在 auth.json 中保存 OPENAI_API_KEY。请清理此供应商的 auth.json 后再切换。"
        );
    }
    Ok(())
}

fn relay_combined_common_config(settings: &BackendSettings) -> String {
    let sections = [
        settings.relay_common_config_contents.trim(),
        settings.relay_context_config_contents.trim(),
    ]
    .into_iter()
    .filter(|section| !section.is_empty())
    .collect::<Vec<_>>();
    if sections.is_empty() {
        String::new()
    } else {
        crate::relay_config::normalize_config_text(&format!("{}\n", sections.join("\n\n")))

View on GitHub (pinned to b1ed92e5e4)