Aider-AI/aider · error · ValueError
Expected `>>>>>>> REPLACE` or `=======`
Error message
Expected `>>>>>>> REPLACE` or `=======`
What it means
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.
Source
Thrown at aider/coders/editblock_coder.py:526
i += 1
if i >= len(lines) or not divider_pattern.match(lines[i].strip()):
raise ValueError(f"Expected `{DIVIDER_ERR}`")
updated_text = []
i += 1
while i < len(lines) and not (
updated_pattern.match(lines[i].strip())
or divider_pattern.match(lines[i].strip())
):
updated_text.append(lines[i])
i += 1
if i >= len(lines) or not (
updated_pattern.match(lines[i].strip())
or divider_pattern.match(lines[i].strip())
):
raise ValueError(f"Expected `{UPDATED_ERR}` or `{DIVIDER_ERR}`")
yield filename, "".join(original_text), "".join(updated_text)
except ValueError as e:
processed = "".join(lines[: i + 1])
err = e.args[0]
raise ValueError(f"{processed}\n^^^ {err}")
i += 1
def find_filename(lines, fence, valid_fnames):
"""
Deepseek Coder v2 has been doing this:
```python
word_count.pyView on GitHub (pinned to 5dc9490bb3)
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.
Example fix
# before <<<<<<< SEARCH old ======= new >>>>>>> (malformed) # after <<<<<<< SEARCH old ======= new >>>>>>> REPLACE
Defensive patterns
Strategy: validation
Validate before calling
def check_block_terminator(text: str) -> str | None:
import re
if not re.search(r"(?m)^>>>>>>> REPLACE$", text):
return "missing '>>>>>>> REPLACE' terminator"
return None Try / catch
try:
edits = list(parse_edits_or_raise(reply))
except ValueError as e:
if "Expected `>>>>>>> REPLACE`" in str(e):
reply = ask_model_to_close_blocks(str(e))
edits = list(parse_edits_or_raise(reply))
else:
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Models abbreviating the closing marker; max_tokens truncation cutting the reply mid-block; hand-written edits pasted into prompts without the full marker grammar.
Related errors
- Bad/missing filename. The filename must be alone on the line
- Expected `=======`
- # {len(failed)} SEARCH/REPLACE {blocks} failed to match!\n
- {processed}\n^^^ {err}
- Delete File action missing path.
AI-assisted analysis of Aider-AI/aider@5dc9490bb3 (2026-08-15).
Data as JSON: /api/errors/a1359466ed7014af.
Report an issue: GitHub.