xai-org/grok-build · error
paths.{key} is not an array
Error message
paths.{key} is not an array What it means
merge_paths adds a PATHS key (e.g. env PATH-style path lists) to a TOML settings table. It inserts an empty array if the key is missing, then requires the existing value to be a TOML array; if the key already exists but holds a non-array value (string, table, etc.) it cannot be merged, so this error is thrown.
Source
Thrown at crates/codegen/xai-grok-shell/src/claude_import.rs:1016
/// are appended. Returns the number of newly added entries.
fn merge_paths(
table: &mut TomlMap<String, TomlValue>,
key: &str,
new_paths: &[&str],
) -> anyhow::Result<usize> {
let paths = table
.entry("paths")
.or_insert_with(|| TomlValue::Table(TomlMap::new()));
let paths_table = paths
.as_table_mut()
.ok_or_else(|| anyhow::anyhow!("[paths] is not a table"))?;
let arr = paths_table
.entry(key)
.or_insert_with(|| TomlValue::Array(Vec::new()));
let existing = arr
.as_array_mut()
.ok_or_else(|| anyhow::anyhow!("paths.{key} is not an array"))?;
let existing_set: std::collections::HashSet<String> = existing
.iter()
.filter_map(|v| v.as_str().map(|s| s.to_string()))
.collect();
let mut count = 0usize;
for p in new_paths {
if !existing_set.contains(*p) {
existing.push(TomlValue::String(p.to_string()));
count += 1;
}
}
Ok(count)
}
/// Merge `Hook` items into `<hooks_dir>/imported-from-claude.json`.
///View on GitHub (pinned to bc7f02eddd)
Solutions
- Open the settings.toml and change paths.<key> to an array of strings, e.g. paths.cfg = ["/usr/bin"]
- Delete the offending paths.<key> line and re-run the import so it is recreated as an empty array
- Validate the TOML with a schema check before running the import
Example fix
# before [paths] cfg = "/usr/local/bin" # after [paths] cfg = ["/usr/local/bin"]
Defensive patterns
Strategy: validation
Validate before calling
// before calling the import
let v = settings.get("paths").and_then(|p| p.get(key));
if let Some(v) = v {
assert!(v.is_array(), "paths.{key} must be an array of strings");
} Type guard
fn is_string_array(v: &toml::Value) -> bool {
v.as_array().map_or(true, |a| a.iter().all(|x| x.is_str()))
} Try / catch
match merge_paths(&mut cfg, key, entries) {
Err(e) if e.to_string().contains("is not an array") => {
// reset the key and retry once
cfg["paths"][key] = toml::Value::Array(vec![]);
merge_paths(&mut cfg, key, entries)
}
r => r,
} Prevention
- Never hand-edit paths entries to bare strings; always use arrays
- Lint settings.toml with a schema before running imports
- Back up settings files before import
When it happens
Trigger: apply_items_to_config / merge_paths is called on a settings.toml in which paths.<key> exists but was hand-edited to a string or inline table instead of an array of strings.
Common situations: Users editing Claude-style settings.toml by hand (e.g. paths.cfg = "/usr/bin" instead of paths.cfg = ["/usr/bin"]), or a schema change from older versions that stored paths as a single string.
Related errors
- marketplace.sources is not an array of tables
- Failed to create agent config: {e}
- Failed to load config: {e}
- Failed to parse config.toml: {e}
- refusing to write import marker: existing config at {} is no
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/4f90823c595b1a81.
Report an issue: GitHub.