jdx/mise · error

failed rename: ->

Error message

failed rename: {} -> {}: {err}

What it means

During `mise dot add`, a staged rename of the source file into place failed mid-apply. The operation bails with the target, source, and underlying OS error; prior steps are handed to rollback via the pushed recovery item. This usually indicates a filesystem-level problem moving the file (permissions, cross-device, missing parent dir).

Solutions

  1. Read the trailing OS error for the root cause (e.g. EXDEV, EACCES, ENOSPC)
  2. Ensure source and target are on the same filesystem, or pre-copy manually before `mise dot add`
  3. Fix permissions on the source file and destination directories
  4. Re-run `mise dot add`; if the run was interrupted, recover state via `mise dot` recovery/journal commands if available
Defensive patterns

Strategy: try-catch

Validate before calling

# preflight: same device and writable destination
df --output=target "$SRC" "$DST_PARENT" && test -w "$DST_PARENT"

Try / catch

match mise_dot_add(...) {
    Err(e) if e.contains("failed rename") => {
        // inspect trailing OS error; fix permissions/device, then retry
    }
    ...
}

Prevention

When it happens

Trigger: The internal rename step returns Err while applying a new dotfile; the code bails with `failed rename: {target} -> {source}: {err}`.

Common situations: Source on a different filesystem/device than destination; read-only or permission-restricted directory; parent directory deleted mid-run; disk full.

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@533346cc37 (2026-09-17). Data as JSON: /api/errors/173a52437f7c2574. Report an issue: GitHub.

Appendix: source

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

                                    )
                                })?;
                                let recovery = tempfile::Builder::new()
                                    .prefix(".mise-dotfiles-rollback-")
                                    .tempdir_in(parent)?;
                                let recovery_path = recovery.path().join("target");
                                // Keep the original on its own filesystem until
                                // the entire transaction succeeds. This makes
                                // rollback an atomic rename instead of another
                                // potentially failing recursive removal.
                                file::rename(&item.target, &recovery_path)?;
                                moved_targets.push(MovedTarget {
                                    target: item.target.clone(),
                                    source: item.source.clone(),
                                    recovery: Some(recovery),
                                });
                                system::files::copy_path(&recovery_path, &item.source)?;
                            }
                            Err(err) => bail!(
                                "failed rename: {} -> {}: {err}",
                                item.target.display_user(),
                                item.source.display_user()
                            ),
                        }
                        journal::commit_changes(pending);
                        info!(
                            "dotfiles: moved {} to {}",
                            item.target.display_user(),
                            item.source.display_user()
                        );
                    } else {
                        target_backups.push((
                            item.target.clone(),
                            backup_path(
                                &item.target,
                                &backup_dir.path().join("targets").join(index.to_string()),
                            )?,

View on GitHub (pinned to 533346cc37)