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

  1. Open the reported global config file and change `history` to a table: `[history]`
  2. Remove the invalid scalar `history` key and let mise recreate `[history] exclude`
  3. 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

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


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));
        true

View on GitHub (pinned to 533346cc37)