can1357/oh-my-pi · error · ParseError
Line numbers must be >= 1 (got ${oldStartLine})
Error message
Line numbers must be >= 1 (got ${oldStartLine}) What it means
Thrown after header parsing when the resolved old start line (from a unified header or a line hint) is defined but less than 1. This is a final safety net covering paths that set oldStartLine outside the unified-header branch (e.g. context line hints), enforcing 1-based line numbers before any hunk content is consumed.
Source
Thrown at packages/coding-agent/src/edit/diff.ts:617
} else if (trimmedContextValue.length > 0) {
changeContexts.push(contextValue);
}
startIndex = 1;
} else if (isHeaderLine) {
const contextValue = headerTrimmed.slice(2).trim();
if (contextValue.length > 0) {
changeContexts.push(contextValue);
}
startIndex = 1;
} else {
if (!allowMissingContext) {
throw new ParseError(`Expected hunk to start with @@ context marker, got: '${lines[0]}'`, lineNumber);
}
startIndex = 0;
}
if (oldStartLine !== undefined && oldStartLine < 1) {
throw new ParseError(`Line numbers must be >= 1 (got ${oldStartLine})`, lineNumber);
}
if (newStartLine !== undefined && newStartLine < 1) {
throw new ParseError(`Line numbers must be >= 1 (got ${newStartLine})`, lineNumber);
}
while (startIndex < lines.length) {
const nextLine = lines[startIndex];
if (!nextLine.startsWith("@@")) {
break;
}
const trimmed = nextLine.trimEnd();
if (trimmed.startsWith(CHANGE_CONTEXT_MARKER)) {
const nestedContext = trimmed.slice(CHANGE_CONTEXT_MARKER.length);
if (nestedContext.trim().length > 0) {
changeContexts.push(nestedContext);
}
startIndex++;
} else if (trimmed === EMPTY_CHANGE_CONTEXT_MARKER) {View on GitHub (pinned to 9690622007)
Solutions
- Renumber the old-side start line to >= 1 in the '@@' header.
- Use the top-of-file marker instead of a line-0 hint.
- Fix the upstream generator's index base (add 1).
- Pre-validate parsed header numbers before handing the diff to the parser.
Example fix
// before @@ util.ts line 0 // after @@ util.ts line 1
Defensive patterns
Strategy: validation
Validate before calling
// after extracting oldStartLine from any header form
if (oldStartLine !== undefined && oldStartLine < 1) {
throw new Error(`old start line must be >= 1, got ${oldStartLine}`);
} Try / catch
try {
hunks = parseDiffHunks(diff);
} catch (err) {
if (err instanceof ParseError && err.message.startsWith("Line numbers must be >= 1")) {
// renumber and retry
} else throw err;
} Prevention
- Standardize on 1-based line numbers across all header forms (unified and context hints).
- Reject 'line 0' at patch-generation time, not parse time.
- Round-trip test: generate a patch, parse it, confirm no ParseError.
When it happens
Trigger: parseOneHunk with a header that yields oldStartLine = 0 or negative — typically an '@@' context header with a 'line 0' hint that somehow bypassed the hint-specific check, or programmatic construction of the header object.
Common situations: Generated patches using 0-based line numbers; tooling that writes '@@ line 0' meaning top-of-file; round-tripping diffs through custom formatters that renumber lines.
Related errors
- Line numbers in @@ header must be >= 1
- Line hint must be >= 1
- Line numbers must be >= 1 (got ${newStartLine})
- Unknown changelog category: ${raw}
- No JSON payload found in response
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/8ab89fd56f4f8705.
Report an issue: GitHub.