can1357/oh-my-pi · error · ParseError
Diff does not contain any lines
Error message
Diff does not contain any lines
What it means
parseOneHunk in the unified-diff parser throws when asked to parse a hunk from an empty remaining line list. It is the boundary guard for a diff that ends (or a hunk header that points past the end) with no hunk body lines available.
Source
Thrown at packages/coding-agent/src/edit/diff.ts:558
changeContext: changeContext && changeContext.length > 0 ? changeContext : undefined,
};
}
function isUnifiedDiffMetadataLine(line: string): boolean {
return matchesTrimmedPrefix(
line,
DIFF_METADATA_PREFIXES.filter(prefix => !prefix.startsWith("*** ")),
);
}
interface ParseHunkResult {
hunk: DiffHunk;
linesConsumed: number;
}
function parseOneHunk(lines: string[], lineNumber: number, allowMissingContext: boolean): ParseHunkResult {
if (lines.length === 0) {
throw new ParseError("Diff does not contain any lines", lineNumber);
}
const changeContexts: string[] = [];
let oldStartLine: number | undefined;
let newStartLine: number | undefined;
let startIndex: number;
const headerLine = lines[0];
const headerTrimmed = headerLine.trimEnd();
const isHeaderLine = headerLine.startsWith("@@");
const unifiedHeader = isHeaderLine ? parseUnifiedHunkHeader(headerTrimmed) : undefined;
const isEmptyContextMarker = /^@@\s*@@$/.test(headerTrimmed);
if (isHeaderLine && (headerTrimmed === EMPTY_CHANGE_CONTEXT_MARKER || isEmptyContextMarker)) {
startIndex = 1;
} else if (unifiedHeader) {
if (unifiedHeader.oldStartLine < 1 || unifiedHeader.newStartLine < 1) {
throw new ParseError("Line numbers in @@ header must be >= 1", lineNumber);View on GitHub (pinned to 9690622007)
Solutions
- Ensure the diff contains complete hunks: each @@ header followed by its body lines
- Check for truncation at the source (clipboard, token limit, log capture) and regenerate the diff
- Validate the diff is non-empty before invoking the applier
- Catch ParseError and surface 'diff is truncated/empty' to the user
Example fix
// before
await applyLegacyPatch('@@ -1,1 +1,2 @@'); // header with no body
// after
await applyLegacyPatch('@@ -1,1 +1,2 @@\n-old line\n+new line'); Defensive patterns
Strategy: validation
Validate before calling
if (!diffText.includes('@@') || diffText.split('\n').filter(l => l.trim()).length < 2) {
throw new SkipOperation('diff is empty or header-only');
} Type guard
function hasHunkBody(diffText) {
const lines = diffText.split('\n');
const i = lines.findIndex(l => l.startsWith('@@'));
return i !== -1 && i + 1 < lines.length && /^[+\- ]/.test(lines[i + 1]);
} Try / catch
try {
await applyLegacyPatch(diffText);
} catch (err) {
if (err instanceof ParseError && err.message === 'Diff does not contain any lines') {
// surface 'diff is truncated or empty'
}
} Prevention
- Verify diffs contain complete hunks before applying
- Check for truncation at capture time (clipboard, token limits)
- Reject empty diffs early in tool pipelines
When it happens
Trigger: Calling the diff parser (via applyLegacyPatch/parse paths) on a diff whose @@ hunk header is the last line, or a diff body with zero lines — the hunk parser is invoked with lines.length === 0.
Common situations: Unified diff truncated right after an @@ header; empty diff file passed to the applier; a tool generated a header-only diff; line-count mismatches after CR/LF stripping left no body lines.
Related errors
- No files were modified.
- Empty patch. Start with ${OPENER}.
- modified change requires peer root
- Managed skill "${name}" needs a non-empty description.
- Managed skill "${name}" needs a non-empty body.
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/110a86267350de7c.
Report an issue: GitHub.