xai-org/grok-build · critical

refusing to overwrite unparseable {}: {}; save a backup and

Error message

refusing to overwrite unparseable {}: {}; save a backup and fix the syntax error before retrying

What it means

save_config_locked refuses to write a new config over a file it cannot parse. Before saving, it re-reads user_config_path() and parses with parse_existing_config_toml; if parsing fails it aborts with this error rather than destroying the user's (possibly hand-modified) config with a syntax error. The message embeds the path and the parse error and asks the user to keep a backup and fix the syntax first.

Source

Thrown at crates/codegen/xai-grok-shell/src/util/config/persist.rs:27

/// Serializes the read-modify-write in `save_config` so two rapid
/// settings toggles can't interleave and clobber each other.
static SAVE_LOCK: tokio::sync::Mutex<()> = tokio::sync::Mutex::const_new(());
/// Blank (first-run 0-byte file) is an empty table; other unparseable TOML is
/// an error so a silent fallback cannot drop unmodeled sections.
pub(crate) fn parse_existing_config_toml(s: &str) -> Result<TomlValue, toml::de::Error> {
    if s.trim().is_empty() {
        return Ok(TomlValue::Table(TomlMap::new()));
    }
    toml::from_str(s)
}
/// [`save_config`] body; caller must hold [`SAVE_LOCK`].
async fn save_config_locked(config: &Config) -> Result<()> {
    let path = user_config_path();
    let mut root: TomlValue = match tokio::fs::read_to_string(&path).await {
        Ok(s) => match parse_existing_config_toml(&s) {
            Ok(v) => v,
            Err(parse_err) => {
                return Err(anyhow::anyhow!(
                    "refusing to overwrite unparseable {}: {}; save a backup \
                         and fix the syntax error before retrying",
                    path.display(),
                    parse_err,
                ));
            }
        },
        Err(_) => TomlValue::Table(TomlMap::new()),
    };
    if !matches!(root, TomlValue::Table(_)) {
        root = TomlValue::Table(TomlMap::new());
    }
    let table = root.as_table_mut().expect("root must be a table");
    merge_section(table, "cli", &config.cli);
    merge_section(table, "models", &config.models);
    merge_section(table, "ui", &config.ui);
    merge_section(table, "harness", &config.harness);
    merge_section(table, "session", &config.session);

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Read the embedded parse_err in the message to find the file/line of the syntax error
  2. Copy the broken file to a backup (e.g. config.toml.bak) as the message instructs
  3. Fix the TOML syntax error at the reported location with an editor or `tomlcheck`
  4. Re-run update_config once the file parses cleanly

Example fix

# before (broken)
model = "grok-4
max_tokens = 4096
# after
model = "grok-4"
max_tokens = 4096
Defensive patterns

Strategy: validation

Validate before calling

let s = tokio::fs::read_to_string(user_config_path()).await?;
if let Err(e) = s.parse::<toml::Value>() {
    eprintln!("config unparseable: {e}; fix syntax before updating config");
}

Type guard

fn parse_ok(s: &str) -> bool { s.parse::<toml::Value>().is_ok() }

Try / catch

match update_config(|cfg| { /* mutation */ }).await {
    Err(e) if e.to_string().contains("refusing to overwrite unparseable") => {
        std::fs::copy(&cfg_path, "config.toml.bak")?;
        eprintln!("backed up broken config; fix the TOML syntax error and retry");
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling update_config while the existing user config TOML on disk has a parse error (malformed TOML, invalid types in an already-passed section, stray characters), so the preservation of existing content cannot be guaranteed.

Common situations: A manual edit to config.toml introduced a typo; a comment containing an unescaped control character; a merge tool or script mangled the file; encoding issues (non-UTF8 bytes) after an editor or tool rewrote it.

Related errors


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