{"record":{"id":"f48bb2717df39f28","repo":"Aider-AI/aider","slug":"expected","errorCode":null,"errorMessage":"Expected `=======`","messagePattern":"Expected `=======`","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aider/coders/editblock_coder.py","lineNumber":511,"sourceCode":"                else:\n                    filename = find_filename(lines[max(0, i - 3) : i], fence, valid_fnames)\n\n                if not filename:\n                    if current_filename:\n                        filename = current_filename\n                    else:\n                        raise ValueError(missing_filename_err.format(fence=fence))\n\n                current_filename = filename\n\n                original_text = []\n                i += 1\n                while i < len(lines) and not divider_pattern.match(lines[i].strip()):\n                    original_text.append(lines[i])\n                    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","sourceCodeStart":493,"sourceCodeEnd":529,"githubUrl":"https://github.com/Aider-AI/aider/blob/5dc9490bb35f9729ef2c95d00a19ccd30c26339c/aider/coders/editblock_coder.py#L493-L529","documentation":"Raised by the SEARCH/REPLACE parser when, after collecting original_text lines following the opening fence/head, it reaches end-of-input or a line that is not the ======= divider. The SEARCH section must be terminated by a line that is exactly ======= before the REPLACE content begins.","triggerScenarios":"A block where the model forgot the ======= divider, used the wrong number of equals signs (===== or =========), put text on the divider line, or truncated the reply before closing the SEARCH section — the while loop consumes lines until divider_pattern matches, and if it never does (i >= len(lines)) this ValueError fires.","commonSituations":"Models mangling the strict diff-fenced grammar (extra/missing '=' characters); replies truncated by max_tokens so the block ends mid-SEARCH; copy-pasted diffs that use unified-diff markers instead of the ======= divider.","solutions":["Check the error's ^^^ context: it prints the processed lines up to the failure so you can see exactly where the divider is missing or malformed.","Make ======= exactly seven equals signs on its own line between SEARCH and REPLACE sections.","If replies are truncated mid-block, raise max_tokens / output token limits for the model.","Feed the error back to the LLM to re-emit the block with correct markers, or switch to a format the model handles more reliably (udiff/patch)."],"exampleFix":"# before\nfoo.py\n```\n<<<<<<< SEARCH\nold line\n=====  (wrong divider)\nnew line\n>>>>>>> REPLACE\n```\n\n# after\nfoo.py\n```\n<<<<<<< SEARCH\nold line\n=======\nnew line\n>>>>>>> REPLACE\n```","handlingStrategy":"validation","validationCode":"def check_block_grammar(text: str) -> str | None:\n    import re\n    if not re.search(r\"(?m)^=======$\", text):\n        return \"missing '=======' divider between SEARCH and REPLACE\"\n    return None  # None → safe to parse","typeGuard":null,"tryCatchPattern":"try:\n    edits = list(parse_edits_or_raise(reply))\nexcept ValueError as e:\n    if \"Expected `=======`\" in str(e):\n        reply = ask_model_to_fix_dividers(str(e))\n        edits = list(parse_edits_or_raise(reply))\n    else:\n        raise","preventionTips":["Show the model one fully-formed example block (<<<<<<< SEARCH / ======= / >>>>>>> REPLACE) in the system prompt.","Watch for max_tokens truncation: incomplete replies are a top source of missing dividers.","Lint model replies for the exact 7-character markers before handing them to the parser."],"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"}