{"record":{"id":"7140d021071bbc52","repo":"jdx/mise","slug":"dotfiles-is-still-tracked","errorCode":null,"errorMessage":"dotfiles: {} is still tracked","messagePattern":"dotfiles: (.+?) is still tracked","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/dotfiles/untrack.rs","lineNumber":169,"sourceCode":"                table.insert(\"enabled\", Value::Boolean(toml_edit::Formatted::new(false)));\n                doc[\"dotfiles\"][&key] = Item::Value(Value::InlineTable(table));\n                file::write(&local, doc.to_string())?;\n                info!(\n                    \"dotfiles: {key} is also declared in {}; switched off in {}\",\n                    entry\n                        .declared_in\n                        .as_deref()\n                        .map(display_path)\n                        .unwrap_or_else(|| \"another layer\".into()),\n                    display_path(&local)\n                );\n                config = Config::reset().await?;\n                tracked = TrackedSet::from_config(&config)?;\n                if tracked\n                    .entry_for(&path)\n                    .is_some_and(|entry| entry.path == path)\n                {\n                    bail!(\"dotfiles: {} is still tracked\", display_path(&path));\n                }\n            }\n        }\n        // A capture command may invoke untrack itself. Its parent holds the\n        // operation lock and records the new enrollment in its outcome; do\n        // not wait on that parent or commit a competing boundary here.\n        if std::env::var_os(crate::system::history::scope::ENV_VAR).is_some()\n            || crate::system::history::scope::is_active()\n        {\n            info!(\n                \"dotfiles: tracking stopped; the enclosing operation will record the change. Live files and earlier committed versions remain\"\n            );\n            return Ok(());\n        }\n        let store = crate::system::history::checkpoint::Store::open()?;\n        let mut draft = crate::system::history::checkpoint::Draft::new(\n            crate::system::history::store::Trigger::Save,\n        );","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/cli/dotfiles/untrack.rs#L151-L187","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the dotfiles config TOML for a lingering identical declaration and remove it","Re-run `mise dotfiles untrack <path>` after any parent capture operation has finished","Check for hooks or capture commands that re-track the path and disable them before untracking"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"grep -n \"$(basename \"$path\")\" ~/.config/mise/config.toml","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid concurrent capture/untrack operations on the same path","Deduplicate config declarations before untracking"],"tags":["cli","dotfiles","state"],"backgroundTag":"invalid-state-transition","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}