jdx/mise · error
[history] in is not a table
Error message
[history] in {} is not a table What it means
edit_exclude() edits the `[history]` table in the global shared config to add/remove an exclude glob. If the file contains a top-level `history` key whose value is not a TOML table (e.g. a string or array), the code refuses to silently overwrite it and bails with the offending file path.
Solutions
- Open the reported global config file and change `history` to a table: `[history]`
- Remove the invalid scalar `history` key and let mise recreate `[history] exclude`
- Validate the TOML (e.g. with a TOML linter) after editing
Example fix
// before (config.toml) history = "disabled" // after (config.toml) [history] enabled = false
Defensive patterns
Strategy: validation
Validate before calling
grep -E '^history[[:space:]]*=' "${MISE_GLOBAL_CONFIG:-$HOME/.config/mise/config.toml}" && echo 'history must be a [history] table, not a scalar — fix before dot track' Prevention
- Always define history settings under a [history] table in TOML
- Validate config files with a TOML parser after hand edits
- Never set `history = <scalar>` in the global config
When it happens
Trigger: Running `mise dot track`/`untrack` flows that update excludes against a global config where `history` is defined as a non-table value, e.g. `history = "off"` or `history = []`.
Common situations: Hand-edited or AI-generated config with wrong TOML shape; a config written by an older/different tool that used a scalar for history; copy-paste mistakes in config.toml.
Related errors
- [history] exclude in
- backend must be a string or table
- dotfile : encrypt must be a boolean
- [dotfiles]." ": mode symlink-each requires a directory…
- expected `run` to be a string or array of strings
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/1127c5b173c37347.
Report an issue: GitHub.
Appendix: source
Thrown at src/cli/dotfiles/track.rs:527
$ <bold>mise dot track ~/.zshrc ~/.config/hypr</bold>
$ <bold>mise dot track ~/.zshrc --os macos</bold>
$ <bold>mise dot track ~/.config/app/credentials --encrypt</bold>
$ <bold>mise dot 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 533346cc37)