xai-org/grok-build · error

refusing to write import marker: existing config at

Error message

refusing to write import marker: existing config at {} is not valid TOML ({}). Fix the file (or move it aside) and retry.

What it means

write_import_marker refuses to add the claude_compat.imported marker when the existing config file fails TOML parsing. Rewriting the file would drop unrelated sections ([model], [ui], etc.) from a hand-edited config, so the error surfaces the parse failure and asks the user to fix the TOML first.

Solutions

  1. Open the config file at the path in the message and fix the TOML syntax reported by the parse error (often a trailing comma).
  2. Temporarily move the file aside so write_import_marker creates a fresh table, then re-apply your settings.
  3. Validate the file with a TOML linter/parser (e.g. taplo, tomlq) before retrying.

Example fix

// before (config.toml)
[ui]
theme = "dark",

// after
[ui]
theme = "dark"
Defensive patterns

Strategy: validation

Validate before calling

if path.exists() {
    let s = std::fs::read_to_string(&path)?;
    toml::from_str::<toml::Value>(&s)
        .map_err(|e| anyhow::anyhow!("config {} invalid TOML: {}", path.display(), e))?;
}

Type guard

fn is_valid_toml_table(s: &str) -> bool {
    toml::from_str::<toml::Value>(s)
        .map(|v| v.is_table())
        .unwrap_or(false)
}

Try / catch

match write_import_marker(&path) {
    Err(e) if e.to_string().contains("not valid TOML") => {
        eprintln!("Fix config TOML first: {e}");
    }
    Err(e) => return Err(e),
    Ok(()) => {}
}

Prevention

When it happens

Trigger: Calling mark_claude_imported (or write_import_marker) when the target config file exists but contains invalid TOML, e.g. a trailing comma or malformed table header.

Common situations: A user hand-edited their config file and left a trailing comma; another tool corrupted the file; a merge left partial TOML syntax behind.

Related errors


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

Appendix: source

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

        .get("claude_compat")
        .and_then(|v| v.get("imported"))
        .and_then(|v| v.as_bool())
        .unwrap_or(false)
}

/// Write `[claude_compat] imported = true` to `~/.grok/config.toml`.
///
/// Uses the same atomic write pattern as `save_mcp_server_config` (write to
/// `.tmp`, then rename). Creates the file and parent directory if missing.
/// Existing content in the file is preserved.
fn write_import_marker(config_path: &Path) -> anyhow::Result<()> {
    // Surface parse errors instead of silently discarding the file: an atomic
    // rewrite would otherwise drop unrelated sections ([model], [ui], etc.)
    // and overwrite a hand-edited config that just happens to have a trailing
    // comma. The user can fix the TOML and retry.
    let mut root: TomlValue = match std::fs::read_to_string(config_path) {
        Ok(s) => toml::from_str(&s).map_err(|e| {
            anyhow::anyhow!(
                "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()

View on GitHub (pinned to bc7f02eddd)