{"record":{"id":"48dbf7fe7611e442","repo":"jdx/mise","slug":"changed-during-application-left-untouched","errorCode":null,"errorMessage":"{} changed during application; left untouched","messagePattern":"(.+?) changed during application; left untouched","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/sync/directories.rs","lineNumber":129,"sourceCode":"    pub(super) fn apply(&mut self) -> Result<()> {\n        self.validate()?;\n        let pending = journal::begin_changes_with(\n            \"history\",\n            \"directory permissions\",\n            [(self.path.clone(), journal::Capture::Shallow)],\n        )?;\n        if self.before.is_none() {\n            crate::file::create_dir_all(&self.path)?;\n        }\n        set_mode(&self.path, self.desired)?;\n        self.written = observe(&self.path)?;\n        journal::commit_changes(pending);\n        Ok(())\n    }\n\n    pub(super) fn verify_written(&self) -> Result<()> {\n        if observe(&self.path)? != self.written {\n            bail!(\n                \"{} changed during application; left untouched\",\n                crate::file::display_path(&self.path)\n            );\n        }\n        Ok(())\n    }\n\n    pub(super) fn recover(&self) -> Result<()> {\n        if self.written.is_none() {\n            return Ok(());\n        }\n        self.verify_written()?;\n        match self.before {\n            Some((_, _, mode)) => set_mode(&self.path, mode),\n            None => std::fs::remove_dir(&self.path).map_err(Into::into),\n        }\n    }\n}","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/history/sync/directories.rs#L111-L147","documentation":"verify_written() re-observes the directory after permission changes were applied and journaled, comparing against the 'written' snapshot. If the state no longer matches what was just written, something modified it concurrently during application; the step reports failure and leaves the directory untouched rather than fighting the writer.","triggerScenarios":"After chmod/journal commit in apply, another process changed the directory's mode or replaced the directory before verify_written ran.","commonSituations":"File watchers, backup agents, or security tools (e.g. ACL-enforcing daemons) resetting directory permissions; concurrent mise operations.","solutions":["Re-run the pull after identifying what modified the directory immediately after apply.","Disable or reconfigure the tool resetting permissions (watcher, security agent) for managed directories.","Retry when no concurrent writer is active."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"let after = observe(&path)?;\nif after != written { /* concurrent modification detected */ }","typeGuard":null,"tryCatchPattern":"if let Err(e) = apply(&plan) {\n    if e.to_string().contains(\"changed during application\") {\n        // find and stop the interfering writer, then retry\n    }\n}","preventionTips":["Exclude managed directories from permission-resetting daemons","Pause file watchers/backup agents during pulls","Investigate immediately; repeated occurrences indicate an external writer"],"tags":["permissions","filesystem","race-condition","sync"],"backgroundTag":"invalid-state-transition","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}