can1357/oh-my-pi · error · ParseError
Update file hunk for path '${path}' is empty
Error message
Update file hunk for path '${path}' is empty What it means
A '*** Update File:' hunk must be followed by at least one diff/context line. When the parser reaches the next hunk header or end of patch without any diff lines for the update, it throws (non-streaming); streaming mode instead emits an empty-diff hunk to be resolved later.
Source
Thrown at packages/coding-agent/src/edit/apply-patch/parser.ts:157
const line = remaining[0];
if (
line.startsWith("*** Add File:") ||
line.startsWith("*** Delete File:") ||
line.startsWith("*** Update File:")
) {
break;
}
diffLines.push(line);
remaining = remaining.slice(1);
lineNumber++;
}
if (diffLines.length === 0) {
if (streaming) {
hunks.push({ path, op: "update", rename: movePath, diff: "" });
continue;
}
throw new ParseError(`Update file hunk for path '${path}' is empty`, lineNumber);
}
hunks.push({ path, op: "update", rename: movePath, diff: diffLines.join("\n") });
continue;
}
if (streaming) {
break;
}
throw new ParseError(
`'${firstLine}' is not a valid hunk header. Valid hunk headers: '*** Add File: {path}', '*** Delete File: {path}', '*** Update File: {path}'`,
lineNumber,
);
}
return hunks;
}
View on GitHub (pinned to 9690622007)
Solutions
- Provide at least one hunk (e.g. a @@ section with context lines) under every Update File header
- If no changes are needed for that file, remove the Update File hunk entirely
- Check for truncation if the patch came from an LLM and regenerate
- For streaming consumers, handle the empty-diff hunk emitted instead of the throw
Example fix
// before *** Update File: src/a.ts *** End Patch // after *** Update File: src/a.ts @@ -existing line +new line *** End Patch
Defensive patterns
Strategy: validation
Validate before calling
const lines = patchText.split('\n');
for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith('*** Update File:') && !/^\s*@@/.test(lines[i + 1] ?? '')) {
throw new SkipOperation(`Update File hunk at line ${i + 1} has no diff body`);
}
} Try / catch
try {
await applyCodexPatch(patchText);
} catch (err) {
if (err instanceof ParseError && err.message.includes('is empty')) {
// regenerate the patch: a hunk body is missing
}
} Prevention
- Ensure every Update File header is followed by a @@ hunk
- Drop Update File hunks with no changes
- Detect LLM truncation and regenerate
When it happens
Trigger: Parsing a patch containing '*** Update File: path' immediately followed by another hunk header or the End marker with no @@/context/+/- lines in between.
Common situations: Model emitted the Update File header but omitted the body (truncation or laziness); blank lines separating hunks got stripped so only whitespace remained; a rename-only intent ('*** Update File: a -> b') with no content changes.
Related errors
- The first line of the patch must be '*** Begin Patch'
- '${firstLine}' is not a valid hunk header. Valid hunk header
- The last line of the patch must be '*** End Patch'
- No files were modified.
- patch does not apply: {message}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/fe2727a535c0eff2.
Report an issue: GitHub.