jdx/mise · error
save {} before choosing --keep-local
Error message
save {} before choosing --keep-local What it means
Resolving a conflict with --keep-local publishes the currently live file content as the resolution, so the on-disk file must exactly match the version that was last saved into the shared history store. If the live object or its permissions differ from the saved copy, mise refuses to silently pick up unsaved edits and asks you to save (re-sync) the file first. Nothing is written when this error fires.
Source
Thrown at src/system/history/sync/apply.rs:161
else {
continue;
};
if take_remote.contains(&local) || keep_local.contains(&local) {
if take_remote.contains(&local) && keep_local.contains(&local) {
bail!("choose only one resolution for {}", display_path(&local));
}
let live = live_object(repo, &local)?;
let saved = shared.get(&conflict.branch_path).cloned();
let saved_mode = permissions_at(
repo,
planned_head.as_deref(),
&conflict.branch_path,
saved.as_ref(),
)?;
if keep_local.contains(&local)
&& (live != saved || live_permissions(&local)? != saved_mode)
{
bail!("save {} before choosing --keep-local", display_path(&local));
}
let remote = match status.upstream_commit.as_deref() {
Some(head) => repo
.object_at(head, &conflict.branch_path)?
.map(|object| {
if !encrypted.contains(&conflict.branch_path) {
return Ok(object);
}
super::files::decrypt(
repo,
&conflict.branch_path,
&object,
!req.automatic && console::user_attended_stderr(),
)
})
.transpose()?,
None => None,
};View on GitHub (pinned to afd2eddd3a)
Solutions
- Save the current file into the sync store first (run a save/push sync step, or the save command of the history system), then re-run pull with --keep-local.
- If the local edits should be discarded, resolve with --take-remote for this path instead of --keep-local.
- Compare live vs saved state with a dry-run pull to see which paths are affected, restore expected permissions (chmod) if only the mode differs, then retry.
Example fix
# before (file edited after last save) mise bootstrap dotfiles pull --keep-local ~/.zshrc # after: save the current state first, then resolve mise bootstrap dotfiles push ~/.zshrc mise bootstrap dotfiles pull --keep-local ~/.zshrc
Defensive patterns
Strategy: validation
Validate before calling
# shell: ensure no unsaved drift before --keep-local mise bootstrap dotfiles pull --dry-run || true # compare live file with last saved state, e.g. via the status output, then save first mise bootstrap dotfiles push mise bootstrap dotfiles pull --keep-local "$path"
Try / catch
try {
await pull({ keepLocal: [path] });
} catch (e) {
if (/save .* before choosing --keep-local/.test(e.message)) {
await push(); // save live state into the sync store
await pull({ keepLocal: [path] });
} else throw e;
} Prevention
- Always run a save/push after editing a tracked dotfile and before resolving conflicts.
- Avoid chmod-ing tracked files without re-syncing.
- Use --dry-run to detect live-vs-saved drift before choosing keep-local.
When it happens
Trigger: Running `mise bootstrap dotfiles pull --keep-local <path>` while the live file content or permissions differ from `shared.get(branch_path)` (the object recorded in the shared history store), i.e. the file was edited after the last successful sync/save.
Common situations: Editing a dotfile in an editor and immediately trying to resolve the conflict without saving it into the history; permission bits changed via chmod after enrollment; a previous pull/push failed midway leaving the saved copy stale; another tool rewrote the file between syncs.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- sync paused: resolve all {} conflict(s) before sharing resum
- nothing can be applied until the held paths are decided
- cannot synchronize: {reason}
- partial pulls are not supported: apply the complete setup wi
- choose only one resolution for {}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/26f0758ec36a9b8d.
Report an issue: GitHub.