xai-org/grok-build · error

[claude_compat] is not a table

Error message

[claude_compat] is not a table

What it means

write_import_marker found a key named claude_compat in the config whose value is not a table, so an imported marker cannot be inserted into it. The code only creates a table when the key is missing; a non-table existing value triggers this error.

Source

Thrown at crates/codegen/xai-grok-shell/src/claude_import.rs:635

                "refusing to write import marker: existing config at {} is \
                 not valid TOML ({}). Fix the file (or move it aside) and \
                 retry.",
                config_path.display(),
                e
            )
        })?,
        Err(e) if e.kind() == std::io::ErrorKind::NotFound => TomlValue::Table(TomlMap::new()),
        Err(e) => return Err(e.into()),
    };
    let table = root
        .as_table_mut()
        .ok_or_else(|| anyhow::anyhow!("config root is not a table"))?;
    let compat = table
        .entry("claude_compat")
        .or_insert_with(|| TomlValue::Table(TomlMap::new()));
    let compat_table = compat
        .as_table_mut()
        .ok_or_else(|| anyhow::anyhow!("[claude_compat] is not a table"))?;
    compat_table.insert("imported".to_string(), TomlValue::Boolean(true));

    let toml_str = toml::to_string_pretty(&root)?;
    if let Some(parent) = config_path.parent() {
        std::fs::create_dir_all(parent)?;
    }
    let tmp = config_path.with_extension("toml.tmp");
    // Best-effort cleanup of the .tmp file if either write or rename fails so
    // a failed marker write doesn't leave a stale artefact next to the real
    // config (otherwise the next attempt would inherit a half-written file
    // before the rename clobbers it).
    if let Err(e) = std::fs::write(&tmp, &toml_str) {
        let _ = std::fs::remove_file(&tmp);
        return Err(e.into());
    }
    if let Err(e) = std::fs::rename(&tmp, config_path) {
        let _ = std::fs::remove_file(&tmp);
        return Err(e.into());

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Edit the config to replace the scalar claude_compat value with a proper [claude_compat] section.
  2. Remove the offending key entirely and re-run the import so it creates the table.
  3. Set claude_compat = { imported = false } as an inline table before importing.

Example fix

// before (config.toml)
claude_compat = true

// after
[claude_compat]
imported = true
Defensive patterns

Strategy: validation

Validate before calling

let root: toml::Value = toml::from_str(&std::fs::read_to_string(&path)?)?;
if let Some(v) = root.get("claude_compat") {
    if !v.is_table() {
        anyhow::bail!("claude_compat must be a table, got: {:?}", v.type_name());
    }
}

Type guard

fn claude_compat_is_table(root: &toml::Value) -> bool {
    root.get("claude_compat").map(|v| v.is_table()).unwrap_or(true)
}

Try / catch

if let Err(e) = write_import_marker(&path) {
    if e.to_string().contains("[claude_compat] is not a table") {
        eprintln!("Replace scalar claude_compat key with a [claude_compat] section: {e}");
    } else {
        return Err(e.into());
    }
}

Prevention

When it happens

Trigger: The config contains e.g. claude_compat = true or claude_compat = "x" at the root, then mark_claude_imported/write_import_marker runs.

Common situations: A user manually added claude_compat as a boolean or string instead of a [claude_compat] section; a prior tool wrote the key in scalar form.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/e9d038af603d592d. Report an issue: GitHub.