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

  1. Provide at least one hunk (e.g. a @@ section with context lines) under every Update File header
  2. If no changes are needed for that file, remove the Update File hunk entirely
  3. Check for truncation if the patch came from an LLM and regenerate
  4. 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

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


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