BigPizzaV3/CodexPlusPlus · error

供应商「 」没有配置模型列表,无法应用到 Grok

Error message

供应商「{}」没有配置模型列表,无法应用到 Grok

What it means

apply_profile_to_grok converts a RelayProfile's `model_list` into Grok model aliases and writes a Grok config payload. If parsing yields no aliases — meaning the supplier profile has no configured models — there is nothing to write into the Grok config, so the function bails with the supplier's name in the message rather than producing an empty/broken Grok configuration.

Solutions

  1. Open the profile in CodexPlusPlus manager and populate the model_list textarea (e.g. `grok-4, grok-4-fast`) before applying to Grok.
  2. Verify the profile actually selected/saved: re-open the profile and confirm model_list is non-empty.
  3. If applying programmatically, ensure profile.model_list is set: `profile.model_list = "grok-4".into();` before the call.

Example fix

// before
let mut profile = load_profile("my-provider");
apply_profile_to_grok(&profile, &backup_root)?; // panics: empty model_list
// after
let mut profile = load_profile("my-provider");
profile.model_list = "grok-4, grok-4-fast".into();
apply_profile_to_grok(&profile, &backup_root)?;
Defensive patterns

Strategy: validation

Validate before calling

if crate::tools::grok::parse_grok_model_list(&profile.model_list).is_empty() {
    return Err(anyhow::anyhow!("profile '{}' needs a model list before applying to Grok", profile.name));
}
apply_profile_to_grok(&profile, &backup_root)?;

Try / catch

match apply_profile_to_grok(&profile, &backup_root) {
    Ok(payload) => save(payload),
    Err(e) if e.to_string().contains("没有配置模型列表") => prompt_user_to_edit_model_list(&profile.name),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling apply_profile_to_grok(profile, backup_root) where `profile.model_list` is empty, whitespace-only, or contains only entries that parse_grok_model_list discards (e.g. comments or malformed lines).

Common situations: Creating a new provider profile in the manager UI and clicking 'Apply to Grok' before filling in the model list textarea; importing a profile JSON that lacks model_list; clearing the model list to 'reset' it and then applying.

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


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

Appendix: source

Thrown at crates/codex-plus-core/src/tools/grok.rs:132

    }
}

/// 从磁盘读 Grok 的当前状态。
pub fn load_grok_state() -> anyhow::Result<GrokConfigPayload> {
    load_grok_config_from_home(&crate::grok_config::default_grok_home_dir())
}

/// 把一个 profile 写进 Grok 的 `config.toml`。
///
/// 注意:这会**替换掉 Grok 里所有受管的 `[model.*]` 表**(保留 `[ui]`、
/// `[models].web_search` 等未管理字段)。调用方必须在 UI 上把这个后果说清楚。
pub fn apply_profile_to_grok(
    profile: &RelayProfile,
    backup_root: &Path,
) -> anyhow::Result<GrokConfigPayload> {
    let aliases = parse_grok_model_list(&profile.model_list);
    if aliases.is_empty() {
        bail!(
            "供应商「{}」没有配置模型列表,无法应用到 Grok",
            profile.name
        );
    }

    let home = crate::grok_config::default_grok_home_dir();
    apply_profile_to_grok_at(&home, profile, backup_root)
}

/// `apply_profile_to_grok` 的显式 home 版本,测试用。
pub fn apply_profile_to_grok_at(
    home: &Path,
    profile: &RelayProfile,
    backup_root: &Path,
) -> anyhow::Result<GrokConfigPayload> {
    let aliases = parse_grok_model_list(&profile.model_list);
    if aliases.is_empty() {
        bail!(

View on GitHub (pinned to b1ed92e5e4)