can1357/oh-my-pi · error · Error
patch does not apply: {message}
Error message
patch does not apply: {message} What it means
Error::PatchFailed is raised when a patch did not apply — context mismatch, missing target file, or malformed patch input. The message includes the human-readable reason and, when known, the offending path.
Source
Thrown at crates/pi-vcs/src/error.rs:56
/// 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,
/// Process exit code.
exit_code: i32,
/// Captured stdout (may be truncated).
stdout: String,
/// Captured stderr (may be truncated).
stderr: String,
},View on GitHub (pinned to 9690622007)
Solutions
- Regenerate the patch against the current HEAD (`git diff` from an up-to-date base) and retry.
- Apply with more fuzz/context tolerance if the API allows it (equivalent of `git apply -C1 --3way`).
- Check the file in `message` — restore/rename it if the patch expects a path that moved, or rewrite the patch paths.
- If the patch text was mangled in transit, transfer it as a file/bytes (preserving LF) instead of pasting.
Example fix
// before
repo.apply_patch(text)?; // context mismatch, hard error
// after
match repo.apply_patch(text) {
Err(Error::PatchFailed { message, .. }) if message.contains("context") => {
repo.apply_patch_3way(text)?; // retry with 3-way merge
}
Err(e) => return Err(e),
Ok(()) => {}
} Defensive patterns
Strategy: try-catch
Type guard
fn is_patch_failed(err: &pi_vcs::Error) -> bool {
matches!(err, pi_vcs::Error::PatchFailed { .. })
} Try / catch
match repo.apply_patch(patch_text) {
Err(pi_vcs::Error::PatchFailed { message, .. }) => {
log::warn!("patch rejected: {message}; retrying with 3-way merge");
repo.apply_patch_3way(patch_text)?;
}
other => other?,
} Prevention
- Generate patches from the same commit the target worktree is based on; regenerate rather than reuse stale diffs.
- Transfer patch text as files/bytes to avoid whitespace, line-ending, and truncation mangling.
- Normalize line endings (LF) in both patch source and target files before applying.
- Prefer 3-way apply (`--3way`) when the target may have drifted from the patch base.
When it happens
Trigger: Applying a diff whose context lines no longer match the worktree/HEAD content (file edited since the patch was made), applying a diff to a repo where a target file does not exist, or feeding truncated/corrupted diff text into the apply API.
Common situations: Patches emailed or copy-pasted and mangled (whitespace/line-ending drift, CRLF vs LF), diffs against a much older commit, applying AI-generated patches after the file changed, patch line numbers offset beyond fuzz tolerance.
Related errors
- not a repository: {path}
- reference not found: {name}
- object not found: {spec}
- cherry-pick of {sha} is empty
- merge conflict in {} file(s)
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/e751d3ead8ff1d63.
Report an issue: GitHub.