jdx/mise · error

dotfiles: is still tracked

Error message

dotfiles: {} is still tracked

What it means

During untrack, mise reloads its config and tracked set and re-checks the path; if an entry whose path equals the target still exists after the reset, the untrack did not take effect and mise bails rather than silently reporting success. This guards against stale state where the declaration removal did not propagate.

Solutions

  1. Inspect the dotfiles config TOML for a lingering identical declaration and remove it
  2. Re-run `mise dotfiles untrack <path>` after any parent capture operation has finished
  3. Check for hooks or capture commands that re-track the path and disable them before untracking
Defensive patterns

Strategy: retry

Validate before calling

grep -n "$(basename "$path")" ~/.config/mise/config.toml

Prevention

When it happens

Trigger: Untracking a path whose enrollment is re-created or persisted elsewhere (e.g. Git-based capture or an enclosing capture command re-recording it) so that after Config::reset() the entry_for(&path) still matches the exact path.

Common situations: A parent capture process re-enrolls the file while untrack runs, or the TOML config still contains an identical declaration after edit, e.g. duplicated entries or a hook re-adding it.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/7140d021071bbc52. Report an issue: GitHub.

Appendix: source

Thrown at src/cli/dotfiles/untrack.rs:169

                table.insert("enabled", Value::Boolean(toml_edit::Formatted::new(false)));
                doc["dotfiles"][&key] = Item::Value(Value::InlineTable(table));
                file::write(&local, doc.to_string())?;
                info!(
                    "dotfiles: {key} is also declared in {}; switched off in {}",
                    entry
                        .declared_in
                        .as_deref()
                        .map(display_path)
                        .unwrap_or_else(|| "another layer".into()),
                    display_path(&local)
                );
                config = Config::reset().await?;
                tracked = TrackedSet::from_config(&config)?;
                if tracked
                    .entry_for(&path)
                    .is_some_and(|entry| entry.path == path)
                {
                    bail!("dotfiles: {} is still tracked", display_path(&path));
                }
            }
        }
        // A capture command may invoke untrack itself. Its parent holds the
        // operation lock and records the new enrollment in its outcome; do
        // not wait on that parent or commit a competing boundary here.
        if std::env::var_os(crate::system::history::scope::ENV_VAR).is_some()
            || crate::system::history::scope::is_active()
        {
            info!(
                "dotfiles: tracking stopped; the enclosing operation will record the change. Live files and earlier committed versions remain"
            );
            return Ok(());
        }
        let store = crate::system::history::checkpoint::Store::open()?;
        let mut draft = crate::system::history::checkpoint::Draft::new(
            crate::system::history::store::Trigger::Save,
        );

View on GitHub (pinned to 533346cc37)