BigPizzaV3/CodexPlusPlus · error

纯 API 配置写入后未检测到完整 custom provider,请检查 config.toml 和供应商 API…

Error message

纯 API 配置写入后未检测到完整 custom provider,请检查 config.toml 和供应商 API Key。

What it means

After applying a PureApi-mode relay profile, apply_selected_relay_profile re-checks the live home directory via relay_config_status_from_home. If the written config does not register as a complete custom provider (status.configured == false), the switch is treated as failed rather than reporting a half-applied state.

Solutions

  1. Open the profile in the manager and fill in the provider API Key (and base_url) before switching
  2. Inspect the generated ~/.codex/config.toml for a complete [model_providers...] block
  3. Verify auth.json contains OPENAI_API_KEY (or the provider's env key) after the switch
  4. If another tool keeps rewriting config.toml, stop it or re-run the switch last

Example fix

// before
profile.relay_mode = PureApi; // api_key empty
// after
profile.relay_mode = PureApi;
profile.api_key = Some("sk-...".into()); // provider key required
Defensive patterns

Strategy: validation

Validate before calling

const ok = profile.relay_mode !== 'pureApi' || (profile.apiKey && profile.baseUrl);
if (!ok) throw new Error('Pure API mode requires provider API key and base URL');

Type guard

const pureApiReady = (p) => p.relayMode !== 'pureApi' || Boolean(p.apiKey && p.baseUrl);

Try / catch

try { await switchProfile(profile); } catch (e) { if (String(e).includes('纯 API 配置写入后未检测到完整 custom provider')) { openProfileSettingsDialog(); } else throw e; }

Prevention

When it happens

Trigger: Switching to a profile with relay_mode == RelayMode::PureApi where, after writing config.toml (and auth), the resulting config is missing provider essentials — e.g. no custom provider block, missing base_url, or no API key present for the provider.

Common situations: User selected Pure API mode but never entered a provider API Key; provider name/base_url left blank; another tool overwrote config.toml between write and verification; auth.json key injection silently failed leaving no OPENAI_API_KEY.

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


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

Appendix: source

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

    settings: &BackendSettings,
) -> anyhow::Result<RelaySwitchResult> {
    let relay = settings.active_relay_profile();
    let common_config = relay_combined_common_config(settings);
    let result = if relay.relay_mode == RelayMode::Official && !relay.official_mix_api_key {
        let auth_contents =
            (!relay.auth_contents.trim().is_empty()).then_some(relay.auth_contents.as_str());
        crate::relay_config::clear_relay_config_to_home_with_auth(home, auth_contents)?
    } else {
        validate_switch_profile_files(&relay)?;
        crate::relay_config::apply_relay_profile_to_home_with_switch_rules(
            home,
            &relay,
            &common_config,
        )?
    };
    let status = relay_config_status_from_home(home);
    if relay.relay_mode == RelayMode::PureApi && !status.configured {
        anyhow::bail!(
            "纯 API 配置写入后未检测到完整 custom provider,请检查 config.toml 和供应商 API Key。"
        );
    }
    Ok(RelaySwitchResult {
        settings: settings.clone(),
        configured: status.configured,
        backup_path: result.backup_path,
    })
}

fn validate_switch_profile_files(profile: &crate::settings::RelayProfile) -> anyhow::Result<()> {
    if profile.relay_mode != RelayMode::Aggregate && profile.config_contents.trim().is_empty() {
        anyhow::bail!(
            "供应商「{}」缺少独立 config.toml,已停止切换,避免继续显示上一套配置文件。",
            if profile.name.trim().is_empty() {
                profile.id.as_str()
            } else {
                profile.name.as_str()

View on GitHub (pinned to b1ed92e5e4)