xai-org/grok-build · error

refusing to overwrite unparseable

Error message

refusing to overwrite unparseable {}: {}; fix the syntax before retrying

What it means

write_toml_table_if_changed refuses to rewrite a config file whose contents cannot be parsed as TOML, protecting hand-edited or corrupted configs from being clobbered by a generated write. The error carries both the path and the parse error and instructs the user to fix the syntax first.

Solutions

  1. Open the file at the reported path, fix the TOML syntax error shown after the semicolon, then retry the save.
  2. Keep a backup: copy the file aside, delete it so the tool writes a clean one, and re-apply settings manually.
  3. Validate with a TOML parser/linter (`cargo add toml` one-off script or an editor TOML plugin) before retrying.
  4. Check for duplicate/conflicting keys or a truncated file if the parse error is cryptic.

Example fix

# before (invalid TOML)
[mcp_servers]
name = "x
# after (fixed)
[mcp_servers.x]
command = "npx"
args = ["-y", "server"]
Defensive patterns

Strategy: validation

Validate before calling

fn toml_parses(path: &Path) -> Result<(), String> {
    let s = std::fs::read_to_string(path).map_err(|e| e.to_string())?;
    s.parse::<toml::Value>().map(|_| ()).map_err(|e| e.to_string())
}
// guard: if toml_parses(&cfg_path).is_err() { fix syntax before saving }

Try / catch

match save_mcp_server_enabled_in(&cfg_path, name, enabled).await {
    Err(e) if e.to_string().contains("refusing to overwrite unparseable") => {
        let backup = cfg_path.with_extension("toml.bak");
        std::fs::copy(&cfg_path, &backup)?; // preserve user edits
        eprintln!("fix TOML syntax in {} (backup at {})", cfg_path.display(), backup.display());
        Err(e)
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling save_mcp_server_enabled_in / save_user_mcp_server_enabled when parse_existing_config_toml fails on the existing file — i.e. the file exists but contains invalid TOML.

Common situations: A manual edit left a syntax error (unclosed string, bad table header, duplicate keys the parser rejects); a partially written file from an earlier crash; a non-TOML file placed at the config path.

Related errors


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

Appendix: source

Thrown at crates/codegen/xai-grok-shell/src/util/config/mcp.rs:792

    let is_user = path == config_path().as_path();
    let _guard = if is_user {
        Some(super::persist::lock_config_writes().await)
    } else {
        None
    };

    let original = match tokio::fs::read_to_string(path).await {
        Ok(s) => s,
        Err(e) if e.kind() == std::io::ErrorKind::NotFound && is_user => String::new(),
        Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(false),
        Err(e) => {
            return Err(anyhow::anyhow!("failed to read {}: {e}", path.display()));
        }
    };
    let mut root = match super::persist::parse_existing_config_toml(&original) {
        Ok(v) => v,
        Err(parse_err) => {
            return Err(anyhow::anyhow!(
                "refusing to overwrite unparseable {}: {}; fix the syntax before retrying",
                path.display(),
                parse_err
            ));
        }
    };
    let before = toml::to_string_pretty(&root)?;
    let table = root
        .as_table_mut()
        .ok_or_else(|| anyhow::anyhow!("config root is not a table"))?;
    f(table);
    let toml_str = toml::to_string_pretty(&root)?;
    if before == toml_str {
        return Ok(false);
    }
    super::persist::atomic_write_string(path, &toml_str)
        .map_err(|e| anyhow::anyhow!("failed to write {}: {e}", path.display()))?;
    Ok(true)

View on GitHub (pinned to bc7f02eddd)