BigPizzaV3/CodexPlusPlus · error

model_auto_compact 的模型

Error message

model_auto_compact 的模型 {slug} 百分比无效:{value}

What it means

validate_model_auto_compact checks each per-model auto-compact percentage in the model_auto_compact map before it is written into the generated Codex config. parse_compact_percent must accept the value as a valid percentage (e.g. an integer 0-100); if it cannot be parsed, the whole apply is aborted. This guards against writing a malformed compact threshold for a model slug.

Solutions

  1. Change the value in model_auto_compact to a plain integer percent the parser accepts (e.g. "80" not "80%" or "0.8")
  2. Verify the exact format parse_compact_percent accepts in crates/codex-plus-core/src/model_suffix.rs and match it
  3. Remove the offending slug entry from model_auto_compact if per-model compaction is not needed
  4. Check for whitespace or invisible characters in the imported config value

Example fix

// before
"model_auto_compact": { "deepseek-v4-pro": "85%" }
// after
"model_auto_compact": { "deepseek-v4-pro": "85" }
Defensive patterns

Strategy: validation

Validate before calling

function isValidCompactPercent(v) {
  const n = Number(v);
  return Number.isInteger(n) && n >= 0 && n <= 100 && String(v).trim() === String(n);
}
for (const [slug, v] of Object.entries(settings.model_auto_compact ?? {})) {
  if (!isValidCompactPercent(v)) throw new Error(`invalid compact percent for ${slug}: ${v}`);
}

Type guard

const isPlainIntString = (v) => /^\d+$/.test(String(v).trim()) && Number(v) >= 0 && Number(v) <= 100;

Prevention

When it happens

Trigger: Calling apply_relay_profile_to_home_with_switch_rules (or any config-apply path) with a RelayProfile whose model_auto_compact map contains a value that parse_compact_percent rejects — e.g. "85%", "1.5", "abc", "150", empty string, or a percentage with surrounding text.

Common situations: User types a percent sign or decimal into the per-model auto-compact field in the CodexPlusPlus manager UI; config imported from hand-edited JSON with values like "0.9"; a model slug was edited and the value got clobbered.

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/ba74a9080ba03a09. Report an issue: GitHub.

Appendix: source

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

                .ok_or_else(|| anyhow::anyhow!("{field_name} 的模型 {key} 值必须是字符串"))?;
            Ok((key.clone(), value.to_string()))
        })
        .collect()
}

fn validate_model_windows(model_windows: &HashMap<String, String>) -> anyhow::Result<()> {
    for (slug, value) in model_windows {
        if crate::model_suffix::parse_window_token(value).is_none() {
            anyhow::bail!("model_windows 的模型 {slug} 窗口值无效:{value}");
        }
    }
    Ok(())
}

fn validate_model_auto_compact(model_auto_compact: &HashMap<String, String>) -> anyhow::Result<()> {
    for (slug, value) in model_auto_compact {
        if crate::model_suffix::parse_compact_percent(value).is_none() {
            anyhow::bail!("model_auto_compact 的模型 {slug} 百分比无效:{value}");
        }
    }
    Ok(())
}

fn parse_model_metadata_map(metadata_json: &str) -> anyhow::Result<serde_json::Map<String, Value>> {
    if metadata_json.trim().is_empty() {
        return Ok(serde_json::Map::new());
    }
    let value: Value = serde_json::from_str(metadata_json)
        .map_err(|error| anyhow::anyhow!("model_metadata JSON 解析失败:{error}"))?;
    let map = value
        .as_object()
        .ok_or_else(|| anyhow::anyhow!("model_metadata 必须是 JSON 对象"))?;
    for (slug, metadata) in map {
        if !metadata.is_object() {
            anyhow::bail!("model_metadata 的模型 {slug} 值必须是对象");
        }

View on GitHub (pinned to b1ed92e5e4)