BigPizzaV3/CodexPlusPlus · error

Grok 模型别名不能包含控制字符

Error message

Grok 模型别名不能包含控制字符

What it means

validate_request in grok_config.rs checks each model entry of a Grok config save request. An alias containing a Unicode control character (e.g. \n, \t, \r, or other C0/C1 chars) is rejected because aliases become TOML keys / identifiers and control characters would corrupt the config file and lookups. The error is raised before any file is written, so nothing is persisted.

Solutions

  1. Trim the alias and remove all control characters before submitting the request
  2. Ensure each alias is a single-line printable identifier
  3. Add input sanitization at the UI/CLI layer that strips control chars automatically

Example fix

// before
let alias = format!("grok-4\n");
// after
let alias: String = raw_alias.trim().chars().filter(|c| !c.is_control()).collect();
Defensive patterns

Strategy: validation

Validate before calling

fn valid_alias(s: &str) -> bool { let t = s.trim(); !t.is_empty() && !t.chars().any(char::is_control) }

Type guard

fn has_control(s: &str) -> bool { s.chars().any(char::is_control) }

Prevention

When it happens

Trigger: Calling save_grok_config_at (via validate_request) with a request.models entry whose trimmed alias contains any char for which char::is_control is true — most often from copy-pasting a name with a trailing newline/tab, or programmatic input built with line breaks.

Common situations: Pasting model aliases from chat or docs with trailing whitespace/newlines; generating config JSON from a script that forgot to trim; CSV/TSV parsing leaving embedded tabs in the alias field.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at crates/codex-plus-core/src/grok_config.rs:280

        }
        if models.contains_key(alias) {
            bail!("Grok 模型别名与未管理配置冲突:{alias}");
        }
        models.insert(alias, item);
    }
    Ok(())
}

fn validate_request(request: &SaveGrokConfigRequest) -> anyhow::Result<()> {
    let mut aliases = HashSet::new();
    let mut sources = HashSet::new();
    for input in &request.models {
        let alias = input.alias.trim();
        if alias.is_empty() {
            bail!("Grok 模型别名不能为空");
        }
        if alias.chars().any(char::is_control) {
            bail!("Grok 模型别名不能包含控制字符");
        }
        if !aliases.insert(alias.to_string()) {
            bail!("Grok 模型别名重复:{alias}");
        }
        let source = input.source_alias.trim();
        if !source.is_empty() && !sources.insert(source.to_string()) {
            bail!("Grok 模型来源别名重复:{source}");
        }
        if !matches!(
            input.api_backend.trim(),
            "responses" | "chat_completions" | "messages"
        ) {
            bail!("Grok 模型 {alias} 的 API 协议无效");
        }
        if input.context_window == Some(0) {
            bail!("Grok 模型 {alias} 的上下文窗口必须大于 0");
        }
        if input

View on GitHub (pinned to b1ed92e5e4)