{"record":{"id":"5a0bebc68feae6ff","repo":"jdx/mise","slug":"appeared-after-was-protected-nothing-more-w","errorCode":null,"errorMessage":"{} appeared after {} was protected; nothing more was changed","messagePattern":"(.+?) appeared after (.+?) was protected; nothing more was changed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/replay.rs","lineNumber":630,"sourceCode":"        let expected = repo.restored_object_at(&live, &step.tree_path)?;\n        if !same_object(&expected, &current_object(repo, &step.path)?) {\n            bail!(\n                \"{} changed after it was protected; nothing more was changed\",\n                display_path(&step.path)\n            );\n        }\n        let was_directory = step.path.is_dir() && !step.path.is_symlink();\n        let mut empty_dirs = vec![];\n        if was_directory && !matches!(&step.action, Action::Write { mode, .. } if mode == \"040000\")\n        {\n            // replacing or removing a directory removes everything inside\n            // it: a file history would capture must be a step of this plan\n            // (else it appeared after protection); a file history never\n            // covers goes with it, said out loud; empty subdirectories\n            // leave no trace in a snapshot and are recorded for undo\n            let inside = directory_contents(&step.path, steps, tracked)?;\n            if let Some(stray) = inside.appeared.first() {\n                bail!(\n                    \"{} appeared after {} was protected; nothing more was changed\",\n                    display_path(stray),\n                    display_path(&step.path)\n                );\n            }\n            if !inside.uncovered.is_empty() {\n                // only reachable with --force (a type change): say what\n                // goes with the directory that no checkpoint holds\n                warn!(\n                    \"history: {} contains files history does not cover; they are removed with it and cannot be undone: {}\",\n                    display_path(&step.path),\n                    inside\n                        .uncovered\n                        .iter()\n                        .map(display_path)\n                        .collect::<Vec<_>>()\n                        .join(\", \")\n                );","sourceCodeStart":612,"sourceCodeEnd":648,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/history/replay.rs#L612-L648","documentation":"While restoring a directory, mise enumerates its live contents and checks that every file it finds is covered by a step in the plan. A 'stray' file means the directory gained a file after the checkpoint was taken; that file would not be captured by the plan or the undo record, so mise aborts the remaining steps (already-written steps are recorded and undoable).","triggerScenarios":"directory_contents() reports an entry in inside.appeared during a directory restore step in apply_steps — a new file exists under step.path that no plan step accounts for.","commonSituations":"A watcher, package manager, or build task created files (logs, node_modules artifacts, caches) inside the directory between checkpoint and apply.","solutions":["Stop processes generating files inside the restored directory, then re-run the rollback.","Move the stray files out of the restore directory if you want them preserved, then retry.","Narrow the restore scope to individual files instead of the whole directory."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"find <dir> -newer <checkpoint-marker> -type f  # detect files created after protection","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pause file-generating tools (watchers, package managers) before directory restores.","Keep generated artifacts out of directories you plan to restore wholesale.","Prefer file-level restore scopes over whole directories when feasible."],"tags":["history","directory","concurrency","checkpoint"],"backgroundTag":"concurrent-modification-detected","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"}