xai-org/grok-build · error

refusing to import: existing config at {} is not valid TOML

Error message

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

What it means

apply_items_to_config refuses to import Claude settings when the existing config file is not valid TOML. An atomic rewrite would silently discard unrelated sections ([model], [ui], etc.) and overwrite hand-edited content, so the parse error is surfaced instead.

Source

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

    /// Paths of config files that were modified.
    pub modified_files: Vec<String>,
}

impl ImportResult {
    pub fn total(&self) -> usize {
        self.global_count + self.project_count
    }
}

/// Apply items to a single config.toml file using atomic write.
fn apply_items_to_config(config_path: &Path, items: &[ImportableItem]) -> anyhow::Result<usize> {
    // Read existing TOML. 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.
    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 import: 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 mut count = 0usize;

    // Group items by type.
    let mut permissions: Vec<&PermissionRule> = Vec::new();

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Fix the TOML syntax reported in the error at the given config path, then re-run the import.
  2. Move the invalid file aside so the import starts from an empty table, then re-apply settings.
  3. Run a TOML validator on the file before invoking the import.

Example fix

// before (config.toml)
[permission]
allow = ["bash"],

// after
[permission]
allow = ["bash"]
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!("{} is not valid TOML: {}", path.display(), e))?;
}

Type guard

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

Try / catch

match apply_import(items, &path) {
    Err(e) if e.to_string().contains("not valid TOML") => {
        eprintln!("Fix the TOML syntax before importing: {e}");
    }
    Err(e) => return Err(e),
    Ok(n) => println!("imported {n} items"),
}

Prevention

When it happens

Trigger: Calling apply_import (which calls apply_items_to_config) while the target config file exists but has invalid TOML, e.g. a trailing comma after a value.

Common situations: Hand-edited config with a stray trailing comma; partial write from a crashed editor; config generated by another tool with syntax errors.

Related errors


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