BigPizzaV3/CodexPlusPlus · error
活动协议代理需要现有 model_providers.
Error message
活动协议代理需要现有 model_providers.{transport_provider_id} 配置 What it means
ensure_active_protocol_proxy_config_in_home configures the active-protocol proxy by rewriting base_url inside the model_providers.<transport_provider_id> table of config.toml. This error is thrown when that provider entry does not exist (model_providers table missing, or the provider id absent, or it is not a table). The function intentionally does NOT create the provider; it only patches an existing one.
Solutions
- Add (or restore) the `[model_providers.<transport_provider_id>]` table in config.toml with a base_url, matching the id reported in the error.
- Check the active RelayProfile's transport_provider_id and correct it to an existing provider id in config.toml.
- Re-apply the relay profile so CodexPlusPlus writes the provider table before enabling the active-protocol proxy.
- Back up and rebuild config.toml from the profile settings to resync provider ids.
Example fix
// before (config.toml) — missing provider # no [model_providers.deepseek] section // after (config.toml) [model_providers.deepseek] name = "DeepSeek" base_url = "https://api.deepseek.com/v1"
Defensive patterns
Strategy: validation
Validate before calling
let doc = std::fs::read_to_string("~/.codex/config.toml")?.parse::<toml_edit::DocumentMut>()?;
let ok = doc.get("model_providers")
.and_then(|p| p.get(transport_provider_id))
.map(|i| i.is_table())
.unwrap_or(false);
if !ok { /* create the provider table first */ } Type guard
fn provider_exists(doc: &toml_edit::DocumentMut, id: &str) -> bool {
doc.get("model_providers")
.and_then(|p| p.get(id))
.map(|i| i.is_table())
.unwrap_or(false)
} Try / catch
if let Err(e) = ensure_active_protocol_proxy_config_in_home(...) {
if e.to_string().contains("需要现有 model_providers") {
// write the missing [model_providers.<id>] table, then retry
}
} Prevention
- Always create the provider table via the library before enabling the active-protocol proxy
- Keep transport_provider_id in the profile in sync with provider ids actually present in config.toml
- Audit config.toml after profile switches to ensure providers were not dropped
- Never hand-delete a [model_providers.*] section that the active profile references
When it happens
Trigger: Calling the apply flow (apply_relay_profile_to_home_with_switch_rules family) with a profile whose transport_provider_id has no corresponding [model_providers.<id>] table in config.toml — e.g. the provider was deleted, renamed, or the profile references a provider never written by CodexPlusPlus.
Common situations: User manually removed a provider section from config.toml, switched profiles and the target provider id no longer matches, or upgraded the fork and the provider naming scheme changed while old configs remained.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- config.toml TOML 解析失败:
- config.toml TOML 解析失败:
- Dream Skin theme backup belongs to a different config.toml
- 必须是 TOML table
- model_providers. 必须是 TOML table
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/b7cad3a46f3aba0a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/relay_config.rs:323
.with_context(|| format!("读取 {} 失败", config_path.display()))?;
let mut doc = parse_toml_document(&existing)?;
let managed = managed_openai_base_url();
let mut changed = false;
if transport_uses_proxy {
let session_provider_id = active_session_provider_id(&doc);
let transport_provider_id = if session_provider_id == "openai" {
RELAY_PROVIDER.to_string()
} else {
active_or_default_provider_id(&doc)
};
let provider = doc
.get_mut("model_providers")
.and_then(Item::as_table_mut)
.and_then(|providers| providers.get_mut(&transport_provider_id))
.and_then(Item::as_table_mut)
.ok_or_else(|| {
anyhow::anyhow!("活动协议代理需要现有 model_providers.{transport_provider_id} 配置")
})?;
let current = provider
.get("base_url")
.and_then(Item::as_str)
.map(str::trim);
if current != Some(managed.as_str()) {
provider["base_url"] = toml_edit::value(managed.as_str());
changed = true;
}
}
if openai_identity_uses_proxy {
let before = doc
.get(OPENAI_BASE_URL_KEY)
.and_then(Item::as_str)
.map(str::trim)
.map(ToString::to_string);
update_remote_control_openai_base_url(&mut doc, true);View on GitHub (pinned to b1ed92e5e4)