{"record":{"id":"7fb5a49ea8a0f0ad","repo":"can1357/oh-my-pi","slug":"firstline-is-not-a-valid-hunk-header-valid-h","errorCode":null,"errorMessage":"'${firstLine}' is not a valid hunk header. Valid hunk headers: '*** Add File: {path}', '*** Delete File: {path}', '*** Update File: {path}'","messagePattern":"'(.+?)' is not a valid hunk header\\. Valid hunk headers: '\\*\\*\\* Add File: (.+?)', '\\*\\*\\* Delete File: (.+?)', '\\*\\*\\* Update File: (.+?)'","errorType":"validation","errorClass":"ParseError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/edit/apply-patch/parser.ts","lineNumber":167,"sourceCode":"\t\t\t\tlineNumber++;\n\t\t\t}\n\n\t\t\tif (diffLines.length === 0) {\n\t\t\t\tif (streaming) {\n\t\t\t\t\thunks.push({ path, op: \"update\", rename: movePath, diff: \"\" });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow new ParseError(`Update file hunk for path '${path}' is empty`, lineNumber);\n\t\t\t}\n\n\t\t\thunks.push({ path, op: \"update\", rename: movePath, diff: diffLines.join(\"\\n\") });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (streaming) {\n\t\t\tbreak;\n\t\t}\n\t\tthrow new ParseError(\n\t\t\t`'${firstLine}' is not a valid hunk header. Valid hunk headers: '*** Add File: {path}', '*** Delete File: {path}', '*** Update File: {path}'`,\n\t\t\tlineNumber,\n\t\t);\n\t}\n\n\treturn hunks;\n}\n","sourceCodeStart":149,"sourceCodeEnd":175,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/edit/apply-patch/parser.ts#L149-L175","documentation":"Inside a patch, every non-empty line must start a recognized operation: '*** Add File:', '*** Delete File:', or '*** Update File:'. Any other line where a hunk header is expected triggers this ParseError, quoting the offending line and listing valid headers.","triggerScenarios":"A line inside the Begin/End markers doesn't match any hunk-header pattern — e.g. prose comments, unified-diff headers (--- a/x, +++ b/x), misspelled markers ('** Update File:'), or stray content between hunks.","commonSituations":"Model mixed codex-patch format with unified diff syntax; markdown lists or commentary leaked into the patch; typo in the '***' prefix or colon; user hand-edited the patch and broke a header.","solutions":["Replace the offending line with one of the valid headers: '*** Add File: {path}', '*** Delete File: {path}', '*** Update File: {path}'","Strip prose/comments and convert any unified-diff syntax to the codex patch format","Verify the exact '*** ' prefix and 'Path:'-style header spelling","Regenerate the patch from the model with format instructions if it keeps emitting invalid headers"],"exampleFix":"// before\n*** Begin Patch\n--- a/src/a.ts\n+++ b/src/a.ts\n// after\n*** Begin Patch\n*** Update File: src/a.ts\n@@\n-existing\n+new\n*** End Patch","handlingStrategy":"validation","validationCode":"const HEADER = /^\\*\\*\\* (Add|Delete|Update) File: .+/;\nconst body = patchText.split('\\n').filter(l => l.trim() && l.trim() !== '*** Begin Patch' && l.trim() !== '*** End Patch');\nif (body.some(l => !HEADER.test(l) && !l.startsWith('@@') && !/^[+\\- ]/.test(l))) {\n\tthrow new SkipOperation('patch contains invalid hunk headers');\n}","typeGuard":"function isValidHunkHeader(line) {\n\treturn /^\\*\\*\\* (Add|Delete|Update) File: .+/.test(line);\n}","tryCatchPattern":"try {\n\tawait applyCodexPatch(patchText);\n} catch (err) {\n\tif (err instanceof ParseError && err.message.includes('not a valid hunk header')) {\n\t\t// show err.message to the user/model: it quotes the offending line\n\t}\n}","preventionTips":["Never mix unified-diff syntax into codex patches","Strip prose/comments from model output","Quote the offending line (already in the message) when asking the model to fix the patch"],"tags":["patch","parser","format-validation","llm-output"],"backgroundTag":"malformed-patch","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}