{"record":{"id":"5b5a8e8060e17d45","repo":"Aider-AI/aider","slug":"invalid-line-prefix-in-update-section-line","errorCode":null,"errorMessage":"Invalid line prefix in update section: {line}","messagePattern":"Invalid line prefix in update section: (.+?)","errorType":"exception","errorClass":"DiffError","httpStatus":null,"severity":"error","filePath":"aider/coders/patch_coder.py","lineNumber":148,"sourceCode":"        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:\n            # Assume lines without prefix are context if format is loose,\n            # but strict format requires ' '. Raise error for strictness.\n            raise DiffError(f\"Invalid line prefix in update section: {line}\")\n\n        # If mode changes from add/delete back to keep, finalize the previous chunk\n        if mode == \"keep\" and last_mode != \"keep\":\n            if del_lines or ins_lines:\n                chunks.append(\n                    Chunk(\n                        # orig_index is relative to the start of the *context* block found\n                        orig_index=len(context_lines) - len(del_lines),\n                        del_lines=del_lines,\n                        ins_lines=ins_lines,\n                    )\n                )\n            del_lines, ins_lines = [], []\n\n        # Collect lines based on mode\n        if mode == \"delete\":\n            del_lines.append(line_content)\n            context_lines.append(line_content)  # Deleted lines are part of the original context","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/Aider-AI/aider/blob/5dc9490bb35f9729ef2c95d00a19ccd30c26339c/aider/coders/patch_coder.py#L130-L166","documentation":"Raised by PatchCoder's update-section parser when a body line has none of the accepted prefixes: '+' (add), '-' (delete), ' ' (keep/context), or completely blank. The parser is strict — every line in an update section must carry a diff prefix.","triggerScenarios":"A patch in apply_patch grammar where the model wrote raw unprefixed code lines inside the update body — e.g. pasted source without the leading +/-/space markers, or a markdown fence line slipping into the patch.","commonSituations":"Models blending 'patch' edit format with plain code output; users hand-authoring patches and forgetting that context lines need a leading space (including for blank context lines inside hunks, which must be ' ' not '').","solutions":["Prefix every line in the update section: '+' for added, '-' for removed, ' ' for unchanged context.","Blank context lines inside a hunk should be a single space or truly empty only at section boundaries — re-check the failing line named in the error.","Return the error to the LLM (it arrives as ValueError 'Error parsing patch content: Invalid line prefix...') so it re-emits a well-formed patch.","Prefer the fence-free patch template in prompts/system reminders so the model doesn't wrap hunks in markdown fences."],"exampleFix":"# before\n*** Update File: foo.py\n@@\n def f():\n    return 1   (no prefix — raises)\n*** End Patch\n\n# after\n*** Update File: foo.py\n@@\n def f():\n-    return 1\n+    return 2\n*** End Patch","handlingStrategy":"validation","validationCode":"def unprefixed_body_lines(patch_text: str) -> list[int]:\n    bad, in_update = [], False\n    for n, l in enumerate(patch_text.splitlines(), 1):\n        s = l.strip()\n        if s.startswith(\"*** Update File:\"):\n            in_update = True\n        elif s == \"*** End Patch\" or s.startswith((\"*** Add File:\", \"*** Delete File:\")):\n            in_update = False\n        elif in_update and l and not l[0] in \"+- \" and not s.startswith((\"@@\", \"***\")):\n            bad.append(n)\n    return bad  # non-empty line numbers → prefix them before parsing","typeGuard":null,"tryCatchPattern":"try:\n    coder.get_edits(patch_text)\nexcept ValueError as e:\n    if \"Invalid line prefix in update section\" in str(e):\n        patch_text = reemit_with_prefixes(str(e))  # model retry with +/-/space markers\n        coder.get_edits(patch_text)\n    else:\n        raise","preventionTips":["Remind the model in the system prompt that every update-body line needs '+', '-', or ' ' prefix (blank context lines too).","Never paste raw markdown fences inside an update section.","Lint generated patches for unprefixed lines before calling get_edits()."],"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"}