Aider-AI/aider · error · ValueError
Bad/missing filename. The filename must be alone on the line
Error message
Bad/missing filename. The filename must be alone on the line before the opening fence {fence[0]} What it means
Raised by the SEARCH/REPLACE parser in editblock_coder while iterating fenced blocks: the parser hit an opening fence (matched head_pattern), looked back up to 3 lines for a filename (find_filename), found none, and there was no current_filename carried over from a previous block. The filename must sit alone on the line directly before the opening fence (e.g. ```python).
Source
Thrown at aider/coders/editblock_coder.py:500
i += 1 # Skip the closing ```
yield None, "".join(shell_content)
continue
# Check for SEARCH/REPLACE blocks
if head_pattern.match(line.strip()):
try:
# if next line after HEAD exists and is DIVIDER, it's a new file
if i + 1 < len(lines) and divider_pattern.match(lines[i + 1].strip()):
filename = find_filename(lines[max(0, i - 3) : i], fence, None)
else:
filename = find_filename(lines[max(0, i - 3) : i], fence, valid_fnames)
if not filename:
if current_filename:
filename = current_filename
else:
raise ValueError(missing_filename_err.format(fence=fence))
current_filename = filename
original_text = []
i += 1
while i < len(lines) and not divider_pattern.match(lines[i].strip()):
original_text.append(lines[i])
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())
):View on GitHub (pinned to 5dc9490bb3)
Solutions
- Ensure every SEARCH/REPLACE block is preceded by the bare filename on its own line (foo.py) immediately before the fence.
- If driving the coder programmatically, pass valid_fnames for files already in the chat so the parser can pick the filename from context.
- Send the error text back to the LLM — aider's retry loop asks the model to re-emit properly labeled blocks.
- Add the target file to the chat first (/add foo.py) so current_filename/valid_fnames resolution can succeed.
Example fix
# before (LLM reply) Here is the fix: ``` <<<<<<< SEARCH old line ======= new line >>>>>>> REPLACE ``` # after Here is the fix: foo.py ``` <<<<<<< SEARCH old line ======= new line >>>>>>> REPLACE ```
Defensive patterns
Strategy: validation
Validate before calling
import re
FENCE = re.compile(r"^```\w*$")
def blocks_have_filenames(reply: str, known_files: set[str]) -> list[str]:
missing = []
lines = reply.splitlines()
for i, line in enumerate(lines):
if FENCE.match(line.strip()):
before = [l for l in lines[max(0, i - 3):i] if l.strip()]
if not any(l.strip() in known_files for l in before):
missing.append(line)
return missing # non-empty → expect the parser error; fix the reply first Try / catch
try:
edits = list(parse_edits_or_raise(reply))
except ValueError as e:
if "filename must be alone on the line" in str(e):
reply = ask_model_to_relabel_blocks(str(e)) # feed back for retry
edits = list(parse_edits_or_raise(reply))
else:
raise Prevention
- System-prompt the model to put the bare path on its own line immediately before every fence.
- Add target files to the chat (/add) so valid_fnames gives the parser a fallback.
- When pre-processing LLM replies, prepend the missing filename line when only one file is in play.
When it happens
Trigger: An LLM reply containing a SEARCH/REPLACE block whose preceding lines contain no recognizable path — filename omitted, embedded in prose, placed after the fence, or written with the fence on the same line. Fires on the first block of a reply (no current_filename fallback) or when filename detection fails for a later block after the previous one had no filename either.
Common situations: Models that wrap code in fences without naming the file (DeepSeek-style outputs the code comments on); filenames written as 'File: foo.py' or inside backticks with other text so find_filename's heuristics miss them; chat history where earlier blocks already consumed/lost the filename context.
Related errors
- Expected `=======`
- Expected `>>>>>>> REPLACE` or `=======`
- # {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/36616184b5f764aa.
Report an issue: GitHub.