{"record":{"id":"a1359466ed7014af","repo":"Aider-AI/aider","slug":"expected-replace-or","errorCode":null,"errorMessage":"Expected `>>>>>>> REPLACE` or `=======`","messagePattern":"Expected `>>>>>>> REPLACE` or `=======`","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aider/coders/editblock_coder.py","lineNumber":526,"sourceCode":"                    i += 1\n\n                if i >= len(lines) or not divider_pattern.match(lines[i].strip()):\n                    raise ValueError(f\"Expected `{DIVIDER_ERR}`\")\n\n                updated_text = []\n                i += 1\n                while i < len(lines) and not (\n                    updated_pattern.match(lines[i].strip())\n                    or divider_pattern.match(lines[i].strip())\n                ):\n                    updated_text.append(lines[i])\n                    i += 1\n\n                if i >= len(lines) or not (\n                    updated_pattern.match(lines[i].strip())\n                    or divider_pattern.match(lines[i].strip())\n                ):\n                    raise ValueError(f\"Expected `{UPDATED_ERR}` or `{DIVIDER_ERR}`\")\n\n                yield filename, \"\".join(original_text), \"\".join(updated_text)\n\n            except ValueError as e:\n                processed = \"\".join(lines[: i + 1])\n                err = e.args[0]\n                raise ValueError(f\"{processed}\\n^^^ {err}\")\n\n        i += 1\n\n\ndef find_filename(lines, fence, valid_fnames):\n    \"\"\"\n    Deepseek Coder v2 has been doing this:\n\n\n     ```python\n    word_count.py","sourceCodeStart":508,"sourceCodeEnd":544,"githubUrl":"https://github.com/Aider-AI/aider/blob/5dc9490bb35f9729ef2c95d00a19ccd30c26339c/aider/coders/editblock_coder.py#L508-L544","documentation":"Raised by the SEARCH/REPLACE parser when the REPLACE section is not properly terminated: after collecting updated_text lines, the parser expects a >>>>>>> REPLACE line (or another ======= for chained sections) and instead hits end-of-input or an unrelated line. Every REPLACE section must close with >>>>>>> REPLACE.","triggerScenarios":"A block missing the >>>>>>> REPLACE terminator, using the wrong number of '>' characters, or a reply truncated after the replacement content; also when stray text follows the replacement lines instead of the closing marker.","commonSituations":"Models abbreviating the closing marker; max_tokens truncation cutting the reply mid-block; hand-written edits pasted into prompts without the full marker grammar.","solutions":["Inspect the ^^^ context in the message to find where termination was expected.","Ensure each block ends with >>>>>>> REPLACE (exactly seven '>' plus ' REPLACE').","Increase output token budget if truncation is the cause.","Return the error to the model for a corrected re-emit, or switch edit format."],"exampleFix":"# before\n<<<<<<< SEARCH\nold\n=======\nnew\n>>>>>>> (malformed)\n\n# after\n<<<<<<< SEARCH\nold\n=======\nnew\n>>>>>>> REPLACE","handlingStrategy":"validation","validationCode":"def check_block_terminator(text: str) -> str | None:\n    import re\n    if not re.search(r\"(?m)^>>>>>>> REPLACE$\", text):\n        return \"missing '>>>>>>> REPLACE' terminator\"\n    return None","typeGuard":null,"tryCatchPattern":"try:\n    edits = list(parse_edits_or_raise(reply))\nexcept ValueError as e:\n    if \"Expected `>>>>>>> REPLACE`\" in str(e):\n        reply = ask_model_to_close_blocks(str(e))\n        edits = list(parse_edits_or_raise(reply))\n    else:\n        raise","preventionTips":["Validate that the count of '>>>>>>> REPLACE' lines matches the '<<<<<<< SEARCH' lines before parsing.","Raise output token limits if truncation is cutting off closing markers.","Feed the parser's ^^^-annotated error back to the model — it pinpoints the exact line."],"tags":["aider","search-replace","parsing","llm-output"],"backgroundTag":null,"analyzedSha":"5dc9490bb35f9729ef2c95d00a19ccd30c26339c","analyzedAt":"2026-08-15T05:40:10.498Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}