{"record":{"id":"76179c35e8a3981a","repo":"Aider-AI/aider","slug":"invalid-patch-line-found-in-update-section-line","errorCode":null,"errorMessage":"Invalid patch line found in update section: {line}","messagePattern":"Invalid patch line found in update section: (.+?)","errorType":"exception","errorClass":"DiffError","httpStatus":null,"severity":"error","filePath":"aider/coders/patch_coder.py","lineNumber":127,"sourceCode":"        line = lines[index]\n        norm_line = _norm(line)\n\n        # Check for section terminators\n        if norm_line.startswith(\n            (\n                \"@@\",\n                \"*** End Patch\",\n                \"*** Update File:\",\n                \"*** Delete File:\",\n                \"*** Add File:\",\n                \"*** End of File\",  # Special terminator\n            )\n        ):\n            break\n        if norm_line == \"***\":  # Legacy/alternative terminator? Handle just in case.\n            break\n        if norm_line.startswith(\"***\"):  # Invalid line\n            raise DiffError(f\"Invalid patch line found in update section: {line}\")\n\n        index += 1\n        last_mode = mode\n\n        # Determine line type and strip prefix\n        if line.startswith(\"+\"):\n            mode = \"add\"\n            line_content = line[1:]\n        elif line.startswith(\"-\"):\n            mode = \"delete\"\n            line_content = line[1:]\n        elif line.startswith(\" \"):\n            mode = \"keep\"\n            line_content = line[1:]\n        elif line.strip() == \"\":  # Treat blank lines in patch as context ' '\n            mode = \"keep\"\n            line_content = \"\"  # Keep it as a blank line\n        else:","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/Aider-AI/aider/blob/5dc9490bb35f9729ef2c95d00a19ccd30c26339c/aider/coders/patch_coder.py#L109-L145","documentation":"Raised by PatchCoder's update-section parser: while collecting patch body lines it encountered a line beginning with '***' that is not one of the recognized markers ('@@', '*** End Patch', '*** Update File:', '*** Delete File:', '*** Add File:', '*** End of File'). Inside an update body, '***' is reserved for structural markers only.","triggerScenarios":"An LLM emitting a patch (via the 'patch' edit format / apply_patch grammar) whose update section contains a stray '***'-prefixed line — e.g. a C-style comment like '*** note ***', a markdown divider, or a mistyped marker such as '*** Update-File:'.","commonSituations":"Models mixing apply_patch syntax with unified diff or markdown conventions; comment lines in updated code accidentally starting with '***'; typo'd section headers.","solutions":["Remove or reword lines starting with '***' inside the update body (e.g. change '*** note' to '# note').","Verify marker spelling exactly: '*** Update File: path', '*** End Patch', etc.","Send the DiffError back to the model to re-emit a clean patch — PatchCoder.get_edits converts it to ValueError('Error parsing patch content: ...') for that retry loop.","If the target file genuinely contains '***'-prefixed lines, keep them as patch body lines with a leading context space (' *** line') so they parse as kept content."],"exampleFix":"# before\n*** Update File: foo.py\n@@\n context\n-*** legacy banner\n+new code\n*** End Patch\n\n# after\n*** Update File: foo.py\n@@\n context\n- *** legacy banner   (prefix kept-content lines with a space)\n+new code\n*** End Patch","handlingStrategy":"validation","validationCode":"VALID_MARKERS = (\"@@\", \"*** End Patch\", \"*** Update File:\", \"*** Delete File:\", \"*** Add File:\", \"*** End of File\")\n\ndef stray_marker_lines(patch_text: str) -> list[str]:\n    return [\n        l for l in patch_text.splitlines()\n        if l.strip().startswith(\"***\") and l.strip() not in VALID_MARKERS and not l.strip().startswith(tuple(VALID_MARKERS))\n    ]  # non-empty → fix these lines before calling get_edits()","typeGuard":null,"tryCatchPattern":"try:\n    coder.get_edits(patch_text)\nexcept ValueError as e:\n    if \"Invalid patch line found in update section\" in str(e):\n        patch_text = reemit_patch_without_stray_markers(str(e))  # ask the model to fix\n        coder.get_edits(patch_text)\n    else:\n        raise","preventionTips":["Escape or re-prefix any literal '***'-starting content lines in the target file with a leading context space.","Use the exact marker vocabulary ('*** End Patch', '*** Update File: ', ...) in prompts so the model copies it verbatim.","Run a marker lint over generated patches before applying."],"tags":["aider","patch-format","apply-patch","parsing"],"backgroundTag":null,"analyzedSha":"5dc9490bb35f9729ef2c95d00a19ccd30c26339c","analyzedAt":"2026-08-15T05:40:10.498Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}