can1357/oh-my-pi · error · Error
git apply --3way failed for task ${taskId}: ${stderr}
Error message
git apply --3way failed for task ${taskId}: ${stderr} What it means
When merging an isolated task's patch back into the parent worktree, the code first tries plain `git apply`, then retries with `git apply --3way`. If the three-way attempt also fails, it logs diagnostics (exit code, stderr, patch head) and throws with the git stderr embedded so the conflict cause is visible.
Source
Thrown at packages/coding-agent/src/task/worktree.ts:660
try {
await repo.applyPatch(patchText, { threeWay: true });
} catch (err) {
if (!vcs.isVcsError(err)) throw err;
threeWayErr = err;
}
if (threeWayErr) {
const wipPatches = collectWipPatches(baselineWip);
if (wipPatches.length === 0 || !baselineWip) {
const stderr = threeWayErr.stderr.slice(0, 2000);
logger.error("commitToBranch: git apply --3way failed", {
taskId,
exitCode: threeWayErr.exitCode,
stderr,
initialStderr: plainErr.stderr.slice(0, 2000),
patchSize: patchText.length,
patchHead: patchText.slice(0, 500),
});
throw new Error(`git apply --3way failed for task ${taskId}: ${stderr}`);
}
try {
// `git apply --3way` leaves conflict markers in `U` files when
// it can't resolve; reset the worktree so the WIP-seeded retry
// starts from a clean HEAD tree.
await repo.reset("hard", "HEAD");
await applyDeltaOverBaselineWip(tmpDir, taskId, patchText, wipPatches, baselineWip);
} catch (wipErr) {
if (!vcs.isVcsError(wipErr)) throw wipErr;
const stderr = wipErr.stderr.slice(0, 2000);
logger.error("commitToBranch: git apply with baseline WIP failed", {
taskId,
exitCode: wipErr.exitCode,
stderr,
threeWayStderr: threeWayErr.stderr.slice(0, 2000),
initialStderr: plainErr.stderr.slice(0, 2000),
patchSize: patchText.length,
patchHead: patchText.slice(0, 500),View on GitHub (pinned to 9690622007)
Solutions
- Read the embedded stderr to find the conflicting file(s); manually apply the task's changes or rebase them
- Reduce conflict window: merge task results promptly, or re-run the task against the current parent HEAD
- If binary files conflict, apply those hunks manually
Defensive patterns
Strategy: try-catch
Validate before calling
// dry-run the patch before the real 3-way apply const probe = await $`git apply --check --3way patch.diff`.cwd(repoDir).quiet().nothrow(); if (probe.exitCode !== 0) console.error(probe.stderr.text());
Try / catch
try {
await mergeTaskPatch(taskId, patchText);
} catch (err) {
if ((err as Error).message.startsWith("git apply --3way failed")) {
// rebase task branch onto current HEAD and regenerate patch
}
throw err;
} Prevention
- Merge task results promptly before editing the same files in the parent
- Avoid having tasks and the parent touch the same paths
- Keep binary files out of isolated-task diffs (3-way merge can't merge binaries)
When it happens
Trigger: Calling the patch-application path for a task whose diff cannot be applied even with 3-way merge: files changed in both the task worktree and the parent (real conflicts), missing context, or paths deleted/renamed in the parent since the task started.
Common situations: Long-running subagent tasks whose target files were edited in the main worktree meanwhile; binary files (git apply --3way can't merge binaries); patches produced against a stale baseline commit.
Related errors
- git apply with baseline WIP failed for task ${taskId}: ${std
- merge conflict in {} file(s)
- not a repository: {path}
- reference not found: {name}
- object not found: {spec}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/8884b45a4b50a556.
Report an issue: GitHub.