can1357/oh-my-pi · error · Error

merge conflict in {} file(s)

Error message

merge conflict in {} file(s)

What it means

Error::Conflict is raised when a merge-style operation (cherry-pick, stash pop, 3-way apply) hits conflicting changes. The error carries the list of worktree-relative paths left in a conflicted state so callers can present resolution UI or abort programmatically.

Source

Thrown at crates/pi-vcs/src/error.rs:49

	#[error("object not found: {spec}")]
	ObjectNotFound {
		/// The revision or object spec as given by the caller.
		spec: String,
	},

	/// Cherry-picking `sha` produced an empty commit (already applied or
	/// auto-resolved to HEAD). Callers should skip and continue the range —
	/// replaces the historical `/the previous cherry-pick is now empty/` stderr
	/// regex.
	#[error("cherry-pick of {sha} is empty")]
	EmptyCherryPick {
		/// The commit that collapsed to a no-op.
		sha: String,
	},

	/// A merge-style operation (cherry-pick, stash pop, 3-way apply) hit
	/// conflicting changes.
	#[error("merge conflict in {} file(s)", paths.len())]
	Conflict {
		/// Worktree-relative paths left in a conflicted state.
		paths: Vec<String>,
	},

	/// A patch did not apply (context mismatch, missing file, malformed input).
	#[error("patch does not apply: {message}")]
	PatchFailed {
		/// Human-readable reason, including the offending path when known.
		message: String,
	},

	/// A CLI-backed operation (push/fetch/clone, reftable fallback) exited
	/// non-zero. Carries the captured streams for user-facing error surfaces.
	#[error("{}", crate::error::cli_message(command, *exit_code, stdout, stderr))]
	Cli {
		/// Rendered command line (`git push --no-follow-tags …`).
		command:   String,

View on GitHub (pinned to 9690622007)

Solutions

  1. Inspect each path in `paths`, resolve conflict markers by hand (or a merge tool), then `git add` the files and continue the operation.
  2. Abort cleanly if unresolvable: `git cherry-pick --abort` / `git merge --abort` (or the library's abort API) to restore pre-operation state.
  3. Rebase the target branch onto its base first to reduce divergence, then retry the operation.
  4. Use a 3-way apply with a better base ref if the patch context drifted only slightly.

Example fix

// before
repo.cherry_pick("abc123")?; // surfaces raw conflict
// after
match repo.cherry_pick("abc123") {
    Err(Error::Conflict { paths, .. }) => {
        eprintln!("resolve these files first: {paths:?}");
        repo.abort_cherry_pick()?;
    }
    Err(e) => return Err(e),
    Ok(()) => {}
}
Defensive patterns

Strategy: try-catch

Type guard

fn is_conflict(err: &pi_vcs::Error) -> Option<&[String]> {
    match err {
        pi_vcs::Error::Conflict { paths } => Some(paths),
        _ => None,
    }
}

Try / catch

match repo.cherry_pick(sha) {
    Err(pi_vcs::Error::Conflict { paths, .. }) => {
        for p in &paths { eprintln!("conflict marker cleanup needed in {p}"); }
        repo.abort_cherry_pick()?; // restore pre-operation state
    }
    other => other?,
}

Prevention

When it happens

Trigger: Cherry-pick/stash-pop/apply where the incoming change touches lines overlapping different content already in HEAD: e.g. applying a patch built against an old base, popping a stash onto a rebased branch, picking a commit into a heavily diverged branch.

Common situations: Long-lived branches diverging from main, stashes created before a rebase, automated backports after the file was refactored, parallel edits to the same lines by two developers.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/a711a4bcb30b18aa. Report an issue: GitHub.