jdx/mise · error

{}

Error message

{}

What it means

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.

Source

Thrown at src/cli/dotfiles/add.rs:675

            remove_path(path)?;
            match backup {
                PathBackup::Missing => {}
                PathBackup::Copied(backup) => system::files::copy_path(backup, path)?,
                PathBackup::Symlink(target) => {
                    if let Some(parent) = path.parent() {
                        file::create_dir_all(parent)?;
                    }
                    file::make_symlink(target, path)?;
                }
            }
            Ok(())
        })();
        if let Err(err) = result {
            errors.push(format!("{}: {err}", path.display_user()));
        }
    }
    if !errors.is_empty() {
        bail!("{}", errors.join("\n"));
    }
    Ok(())
}

fn remove_path(path: &std::path::Path) -> Result<()> {
    if path.is_symlink() || path.is_file() {
        file::remove_file(path)?;
    } else if path.is_dir() {
        file::remove_all(path)?;
    }
    Ok(())
}

struct MovedTarget {
    target: PathBuf,
    source: PathBuf,
    /// A same-filesystem staging directory used by cross-device captures.
    /// Keeping it alive preserves the original until the transaction commits.

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Inspect each `path: err` line and manually restore that path (e.g. copy the backup back or remove the stray file).
  2. Fix permissions on the affected directories before retrying the rollback/restore.
  3. Re-run the add command once the filesystem state is clean.

Example fix

// manual restoration hinted by the joined errors
mv ~/.config/mise/dotfiles-backups/<hash> ~/.zshrc
chmod 644 ~/.zshrc
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure restore destinations are clear before risky operations
import { accessSync, constants } from 'node:fs';
try { accessSync(targetPath, constants.W_OK); } catch { throw new Error(`not writable: ${targetPath}`); }

Try / catch

// parse each `path: err` line and restore manually
const lines = String(e.stderr).split('\n');
for (const line of lines) console.error('manual restore needed:', line);

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/6b453867acc97845. Report an issue: GitHub.