jdx/mise · error
[history] in {} is not a table
Error message
[history] in {} is not a table What it means
edit_exclude opens the global shared config (toml_edit Document) to append an entry under [history]. If a [history] key exists but holds a non-table value (e.g. a string or array), the code cannot insert an exclude list and bails. This guards against corrupting an unexpectedly typed config section.
Source
Thrown at src/cli/dotfiles/track.rs:476
r#"<bold><underline>Examples:</underline></bold>
$ <bold>mise bootstrap dotfiles track ~/.zshrc ~/.config/hypr</bold>
$ <bold>mise bootstrap dotfiles track ~/.zshrc --os macos</bold>
$ <bold>mise bootstrap dotfiles track ~/.config/app/state.json --no-autosave</bold>
"#
);
/// Adds (or removes) a glob in `[history] exclude` of the global config.
/// Returns whether the file changed.
pub(crate) fn edit_exclude(glob: &str, add: bool) -> Result<bool> {
use toml_edit::{Item, Value};
let global = crate::config::global_shared_config_path();
let mut doc = read_document(&global)?;
let history = doc
.entry("history")
.or_insert(Item::Table(toml_edit::Table::new()));
let Some(table) = history.as_table_mut() else {
eyre::bail!("[history] in {} is not a table", display_path(&global));
};
table.set_implicit(false);
let exclude = table
.entry("exclude")
.or_insert(Item::Value(Value::Array(toml_edit::Array::new())));
let Some(array) = exclude.as_array_mut() else {
eyre::bail!(
"[history] exclude in {} is not an array",
display_path(&global)
);
};
let present = array.iter().any(|value| value.as_str() == Some(glob));
let changed = if add && !present {
array.push(Value::String(toml_edit::Formatted::new(glob.to_string())));
true
} else if !add && present {
array.retain(|value| value.as_str() != Some(glob));
trueView on GitHub (pinned to afd2eddd3a)
Solutions
- Open the global config file shown in the message and convert `history` to a table: `history = "x"` → `[history]\n…`
- Remove the stray `history` key if it is leftover garbage and rerun the exclude command
- Back up the config before editing; toml_edit refuses to overwrite wrong types by design
Example fix
// before (global config.toml) history = "disabled" // after [history] exclude = []
Defensive patterns
Strategy: validation
Validate before calling
# check the global config type before running tomlq '.history | type' ~/.config/mise/config.toml # must be "object"
Try / catch
mise dotfiles track --exclude <glob> || {
grep -n '^history' ~/.config/mise/config.toml
} Prevention
- Never assign a scalar to `history` in the global config
- Validate config.toml with a TOML linter after hand edits
- Keep [history] as a table with exclude as an array
When it happens
Trigger: Running `mise dotfiles track --exclude <glob>` (or untrack --exclude) when the global config file defines `history` as a scalar/array, e.g. `history = "foo"` instead of `[history]`.
Common situations: Hand-edited global config.toml that accidentally made history a value; a tool or older version wrote history as a string; copy-paste merging collisions in the global config.
Related errors
- [history] exclude in {} is not an array
- aqua var `{}` must be a string, got {}
- backend must be a string or table
- dotfile {target}: encrypt must be a boolean
- expected `run` to be a string or array of strings
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/1127c5b173c37347.
Report an issue: GitHub.