BigPizzaV3/CodexPlusPlus · error

当前配置使用外部 model_catalog_json,无法同时应用每模型窗口、自动压缩或元数据

Error message

当前配置使用外部 model_catalog_json,无法同时应用每模型窗口、自动压缩或元数据

What it means

When the managed config.toml already points at an external model_catalog_json file, the library cannot generate a merged catalog that also carries per-model window/auto-compact/metadata overrides; mixing the two is unsafe, so it bails when has_per_model_overrides is true. Without overrides it proceeds by removing or ignoring the pointer.

Solutions

  1. Remove the model_catalog_json key from config.toml so the library can generate its own catalog
  2. Or drop the per-model window/auto-compact/metadata overrides for this apply
  3. Convert the external catalog's entries into in-config model_windows values, then re-apply

Example fix

// before (config.toml)
model_catalog_json = "%userprofile%\\.codex\\codex-models.json"
// after (config.toml)
# key removed; let CodexPlusPlus generate the catalog
Defensive patterns

Strategy: validation

Validate before calling

let doc: toml_edit::DocumentMut = config_text.parse()?;
let has_external = doc.get("model_catalog_json").is_some();
if has_external && has_per_model_overrides {
    return Err(anyhow::anyhow!("移除 model_catalog_json 或取消每模型覆盖"));
}

Try / catch

match apply_relay_profile_to_home_with_switch_rules(...) {
    Err(e) if e.to_string().contains("外部 model_catalog_json") => confirm_remove_catalog_pointer_then_retry(),
    other => other?,
}

Prevention

When it happens

Trigger: Calling the apply pipeline (apply_relay_profile_to_home_with_switch_rules → apply_context_limits_to_config) with per-model overrides while config.toml's model_catalog_json key references an external catalog file, and the catalog is not treated as official-deepseek-responses.

Common situations: User previously enabled an external catalog (e.g. codex-models.json pointer) and now tries to apply per-model windows via model_list[1M] syntax; configs migrated from other tools retain a model_catalog_json pointer.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

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

    let fallback = parse_optional_positive_u64(&profile.context_window, "上下文大小")?;
    // 用户已手写 model_catalog_json 指针时保留,不覆盖(保 preserves_user_model_catalog_json 测试)。
    // Codex++ 管理的 catalog 必须随当前 profile 切换;否则前一个供应商的模型列表会残留。
    // cc-switch 的固定文件名属于已知的其他管理器投影,不视为用户手写 catalog;
    // 切换到 Codex++ profile 时应接管,否则旧 catalog 会继续覆盖本 profile 的模型元数据。
    if let Some(existing) = root_key_string(&config_text, "model_catalog_json") {
        if existing != catalog_relative {
            if is_codex_plus_managed_model_catalog(home, &existing)
                || is_cc_switch_model_catalog(&existing)
            {
                config_text = remove_root_key(&config_text, "model_catalog_json");
            } else if model_catalog_pointer_has_unexpanded_variable(&existing) {
                // `%userprofile%\.codex\codex-models.json` 这类指针 codex 不展开变量,
                // 在任何机器上都读不到,留着会让 codex 拒绝加载整份 config.toml
                // (#2123)。去掉它不会比现在更差——这份 catalog 反正从未生效过。
                config_text = remove_root_key(&config_text, "model_catalog_json");
            } else {
                if has_per_model_overrides {
                    anyhow::bail!(
                        "当前配置使用外部 model_catalog_json,无法同时应用每模型窗口、自动压缩或元数据"
                    );
                }
                if official_deepseek_responses {
                    return Ok(config_text.to_string());
                }
                if custom_responses
                    && copy_standard_responses_catalog(
                        home,
                        &existing,
                        &catalog_relative,
                        &entries,
                        fallback,
                    )?
                {
                    let mut doc = parse_toml_document(&config_text)?;
                    doc["model_catalog_json"] = toml_edit::value(catalog_relative);
                    return Ok(normalize_optional_toml(doc));

View on GitHub (pinned to b1ed92e5e4)