xai-org/grok-build · error

refusing to overwrite unparseable {}: {}; fix the syntax bef

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.

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)

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.