xai-org/grok-build · error
permission.{key} is not an array
Error message
permission.{key} is not an array What it means
merge_permissions found permission.allow (or permission.deny, etc.) present but not as a TOML array, so rule strings cannot be appended/deduped. Only a missing key gets a fresh empty array; an existing non-array value errors out.
Source
Thrown at crates/codegen/xai-grok-shell/src/claude_import.rs:891
RuleAction::Ask => ask_rules.push(formatted),
}
}
for (key, new_rules) in [
("allow", allow_rules),
("deny", deny_rules),
("ask", ask_rules),
] {
if new_rules.is_empty() {
continue;
}
let arr = perm_table
.entry(key)
.or_insert_with(|| TomlValue::Array(Vec::new()));
let existing = arr
.as_array_mut()
.ok_or_else(|| anyhow::anyhow!("permission.{key} is not an array"))?;
// Collect existing strings for dedup.
let existing_set: std::collections::HashSet<String> = existing
.iter()
.filter_map(|v| v.as_str().map(|s| s.to_string()))
.collect();
for rule_str in new_rules {
if !existing_set.contains(&rule_str) {
existing.push(TomlValue::String(rule_str));
count += 1;
}
}
}
Ok(count)
}
View on GitHub (pinned to bc7f02eddd)
Solutions
- Convert the value to an array: allow = ["bash", "read"].
- Remove the malformed key so merge_permissions creates a fresh array and merges rules.
- Ensure all rule entries are strings, not tables or scalars.
Example fix
// before (config.toml) [permission] allow = "bash" // after [permission] allow = ["bash"]
Defensive patterns
Strategy: validation
Validate before calling
let root: toml::Value = toml::from_str(&std::fs::read_to_string(&path)?)?;
for key in ["allow", "deny"] {
if let Some(v) = root.get("permission").and_then(|p| p.get(key)) {
if !v.is_array() {
anyhow::bail!("permission.{key} must be an array of strings");
}
}
} Type guard
fn rule_is_string_array(v: &toml::Value) -> bool {
v.as_array().map(|a| a.iter().all(|x| x.is_str())).unwrap_or(false)
} Try / catch
if let Err(e) = apply_import(items, &path) {
if e.to_string().contains("is not an array") {
eprintln!("Wrap rule values in [ ... ], e.g. allow = [\"bash\"]");
} else {
return Err(e.into());
}
} Prevention
- Always express permission rules as arrays of strings, even for a single rule.
- Validate permission.* values are arrays before importing.
- Copy the section shape from generated examples rather than inventing syntax.
When it happens
Trigger: apply_items_to_config merges rules while permission.allow (or another action key) is set to a string, boolean, or table instead of an array of strings.
Common situations: Hand-edit produced allow = "bash" instead of allow = ["bash"]; an inline table was placed where the array belongs.
Related errors
- config root is not a table
- [claude_compat] is not a table
- [permission] is not a table
- [mcp_servers] is not a table
- [paths] is not a table
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/a0bbcc798ec94c17.
Report an issue: GitHub.