{"record":{"id":"6b453867acc97845","repo":"jdx/mise","slug":"error-6b4538","errorCode":null,"errorMessage":"{}","messagePattern":"\\{\\}","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/dotfiles/add.rs","lineNumber":675,"sourceCode":"            remove_path(path)?;\n            match backup {\n                PathBackup::Missing => {}\n                PathBackup::Copied(backup) => system::files::copy_path(backup, path)?,\n                PathBackup::Symlink(target) => {\n                    if let Some(parent) = path.parent() {\n                        file::create_dir_all(parent)?;\n                    }\n                    file::make_symlink(target, path)?;\n                }\n            }\n            Ok(())\n        })();\n        if let Err(err) = result {\n            errors.push(format!(\"{}: {err}\", path.display_user()));\n        }\n    }\n    if !errors.is_empty() {\n        bail!(\"{}\", errors.join(\"\\n\"));\n    }\n    Ok(())\n}\n\nfn remove_path(path: &std::path::Path) -> Result<()> {\n    if path.is_symlink() || path.is_file() {\n        file::remove_file(path)?;\n    } else if path.is_dir() {\n        file::remove_all(path)?;\n    }\n    Ok(())\n}\n\nstruct MovedTarget {\n    target: PathBuf,\n    source: PathBuf,\n    /// A same-filesystem staging directory used by cross-device captures.\n    /// Keeping it alive preserves the original until the transaction commits.","sourceCodeStart":657,"sourceCodeEnd":693,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/cli/dotfiles/add.rs#L657-L693","documentation":"restore_paths collects one error per path it fails to restore (removing or moving a path back during rollback) and, if any occurred, bails with all of them joined by newlines — hence the bare `\"{}\"` format. It is invoked from rollback_add, so this is the per-path layer of the add-command rollback reporting.","triggerScenarios":"Any restore action on a rolled-back path fails: remove_path failing on a file/symlink (permissions, ENOENT already gone handled?), or move of the backup back to the original location failing (cross-device, destination not empty).","commonSituations":"Files created by other processes in the target location during the run; permission changes mid-operation; backups on a different mount than the original path.","solutions":["Inspect each `path: err` line and manually restore that path (e.g. copy the backup back or remove the stray file).","Fix permissions on the affected directories before retrying the rollback/restore.","Re-run the add command once the filesystem state is clean."],"exampleFix":"// manual restoration hinted by the joined errors\nmv ~/.config/mise/dotfiles-backups/<hash> ~/.zshrc\nchmod 644 ~/.zshrc","handlingStrategy":"try-catch","validationCode":"// ensure restore destinations are clear before risky operations\nimport { accessSync, constants } from 'node:fs';\ntry { accessSync(targetPath, constants.W_OK); } catch { throw new Error(`not writable: ${targetPath}`); }","typeGuard":null,"tryCatchPattern":"// parse each `path: err` line and restore manually\nconst lines = String(e.stderr).split('\\n');\nfor (const line of lines) console.error('manual restore needed:', line);","preventionTips":["Keep backup directories on the same filesystem as the originals.","Avoid concurrent processes touching dotfile paths during add/rollback.","Check permissions on dotfiles before running add."],"tags":["filesystem","dotfiles","rollback","restore-failed"],"backgroundTag":"file-write-failed","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"}