{"record":{"id":"1ff1732274d4c8fe","repo":"can1357/oh-my-pi","slug":"line-numbers-in-header-must-be-1","errorCode":null,"errorMessage":"Line numbers in @@ header must be >= 1","messagePattern":"Line numbers in @@ header must be >= 1","errorType":"validation","errorClass":"ParseError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/edit/diff.ts","lineNumber":576,"sourceCode":"\t\tthrow new ParseError(\"Diff does not contain any lines\", lineNumber);\n\t}\n\n\tconst changeContexts: string[] = [];\n\tlet oldStartLine: number | undefined;\n\tlet newStartLine: number | undefined;\n\tlet startIndex: number;\n\n\tconst headerLine = lines[0];\n\tconst headerTrimmed = headerLine.trimEnd();\n\tconst isHeaderLine = headerLine.startsWith(\"@@\");\n\tconst unifiedHeader = isHeaderLine ? parseUnifiedHunkHeader(headerTrimmed) : undefined;\n\tconst isEmptyContextMarker = /^@@\\s*@@$/.test(headerTrimmed);\n\n\tif (isHeaderLine && (headerTrimmed === EMPTY_CHANGE_CONTEXT_MARKER || isEmptyContextMarker)) {\n\t\tstartIndex = 1;\n\t} else if (unifiedHeader) {\n\t\tif (unifiedHeader.oldStartLine < 1 || unifiedHeader.newStartLine < 1) {\n\t\t\tthrow new ParseError(\"Line numbers in @@ header must be >= 1\", lineNumber);\n\t\t}\n\t\tif (unifiedHeader.changeContext) {\n\t\t\tchangeContexts.push(unifiedHeader.changeContext);\n\t\t}\n\t\toldStartLine = unifiedHeader.oldStartLine;\n\t\tnewStartLine = unifiedHeader.newStartLine;\n\t\tstartIndex = 1;\n\t} else if (isHeaderLine && headerTrimmed.startsWith(CHANGE_CONTEXT_MARKER)) {\n\t\tconst contextValue = headerTrimmed.slice(CHANGE_CONTEXT_MARKER.length);\n\t\tconst trimmedContextValue = contextValue.trim();\n\t\tconst normalizedContextValue = trimmedContextValue.replace(/^@@\\s*/u, \"\");\n\n\t\tconst lineHintMatch = normalizedContextValue.match(LINE_HINT_REGEX);\n\t\tif (lineHintMatch) {\n\t\t\toldStartLine = Number(lineHintMatch[1]);\n\t\t\tnewStartLine = oldStartLine;\n\t\t\tif (oldStartLine < 1) {\n\t\t\t\tthrow new ParseError(\"Line hint must be >= 1\", lineNumber);","sourceCodeStart":558,"sourceCodeEnd":594,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/edit/diff.ts#L558-L594","documentation":"This ParseError is thrown by parseOneHunk when a hunk starts with a standard unified-diff '@@ -a,b +c,d @@' header whose old or new start line number is less than 1. The parser requires every line number in the header to be a positive 1-based index; 0 or negative values are invalid in unified diffs. The library throws so callers get a precise, line-attributed message instead of applying a patch at a bogus location.","triggerScenarios":"Calling parseDiffHunks or parseOneHunk with a diff whose first line matches UNIFIED_HUNK_HEADER_REGEX but contains a start line of 0 or a negative number, e.g. '@@ -0,0 +1,3 @@' or '@@ -5 +0 @@'.","commonSituations":"Hand-written patches where the author counts lines from 0; diffs generated against an empty/new file and mis-computed by custom tooling; tools that emit '@@ -0,0' for file-creation hunks (valid in git but rejected here since it implies insert-at-zero).","solutions":["Renumber the hunk header so both start lines are >= 1 (new/empty files typically use '+1,N').","If the patch targets a brand-new file, start the hunk at line 1 rather than 0.","Regenerate the patch with the producing tool instead of hand-editing the header.","Wrap the parse in try-catch for ParseError and surface the failing line number to the user."],"exampleFix":"// before\n@@ -0,0 +1,3 @@\n+new line\n// after\n@@ -1,3 +1,3 @@\n new line","handlingStrategy":"validation","validationCode":"const m = firstLine.match(/^@@ -(\\d+)(?:,\\d+)? \\+(\\d+)(?:,\\d+)? @@/);\nif (m && (Number(m[1]) < 1 || Number(m[2]) < 1)) {\n  throw new Error(`Hunk header start lines must be >= 1, got -${m[1]} +${m[2]}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  hunks = parseDiffHunks(diff);\n} catch (err) {\n  if (err instanceof ParseError && err.message.includes(\"must be >= 1\")) {\n    // surface err.lineNumber and the offending header to the user / fix generator\n  } else throw err;\n}","preventionTips":["Always generate headers with 1-based line numbers; never emit 0.","For new files, use '+1,N' for the new side.","Test your diff generator against empty-file and file-creation cases."],"tags":["diff","parsing","validation"],"backgroundTag":"invalid-hunk-header","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}