{"record":{"id":"02b940009141c76a","repo":"can1357/oh-my-pi","slug":"line-hint-must-be-1","errorCode":null,"errorMessage":"Line hint must be >= 1","messagePattern":"Line hint must be >= 1","errorType":"validation","errorClass":"ParseError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/edit/diff.ts","lineNumber":594,"sourceCode":"\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);\n\t\t\t}\n\t\t} else if (TOP_OF_FILE_REGEX.test(normalizedContextValue)) {\n\t\t\toldStartLine = 1;\n\t\t\tnewStartLine = 1;\n\t\t} else if (trimmedContextValue.length > 0) {\n\t\t\tchangeContexts.push(contextValue);\n\t\t}\n\t\tstartIndex = 1;\n\t} else if (isHeaderLine) {\n\t\tconst contextValue = headerTrimmed.slice(2).trim();\n\t\tif (contextValue.length > 0) {\n\t\t\tchangeContexts.push(contextValue);\n\t\t}\n\t\tstartIndex = 1;\n\t} else {\n\t\tif (!allowMissingContext) {\n\t\t\tthrow new ParseError(`Expected hunk to start with @@ context marker, got: '${lines[0]}'`, lineNumber);\n\t\t}","sourceCodeStart":576,"sourceCodeEnd":612,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/edit/diff.ts#L576-L612","documentation":"Thrown when an '@@' change-context header carries a line hint (e.g. '@@ near line 0') parsed by LINE_HINT_REGEX and the extracted hint is less than 1. Line hints resolve ambiguous context markers to a concrete anchor line, and the parser enforces 1-based positive numbering just like unified headers. It fails fast at the header line rather than mis-anchoring the patch.","triggerScenarios":"Calling parseDiffHunks on a patch whose context header contains a line hint of 0 or negative, e.g. '@@ foo.js line 0' or '@@ near line -2'.","commonSituations":"LLM- or template-generated patches where a 'line 0' hint means 'top of file'; scripts that compute hint line numbers with 0-based indices; hand-edited patches after copy/paste.","solutions":["Change the line hint to 1-based: use 'line 1' or a top-of-file marker instead of 'line 0'.","Drop the line hint entirely and let the surrounding context text locate the hunk.","Fix the generating code to add 1 when converting from 0-based indices.","Pre-validate header hints with a regex before calling the parser."],"exampleFix":"// before\n@@ src/app.ts line 0\n// after\n@@ src/app.ts line 1","handlingStrategy":"validation","validationCode":"const hint = contextHeader.match(/line\\s+(-?\\d+)/i);\nif (hint && Number(hint[1]) < 1) {\n  throw new Error(`Line hint must be >= 1, got ${hint[1]}; use 'line 1' or top-of-file`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  hunks = parseDiffHunks(diff);\n} catch (err) {\n  if (err instanceof ParseError && err.message === \"Line hint must be >= 1\") {\n    // rewrite 'line 0' hints to 'line 1' and retry once\n  } else throw err;\n}","preventionTips":["Emit 1-based line hints; map 'line 0' meaning top-of-file to a top-of-file marker.","Prefer anchoring hunks with surrounding context text instead of numeric hints.","Add 1 when converting from 0-based indices in generator code."],"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"}