Skip to content

BUG: find_filename misses filenames when fenced block markers are indented #5662

Description

@Jingyi1003

Summary

find_filename can miss a valid filename when the surrounding fenced block markers have leading whitespace.

Aider already supports recovering filenames from fenced blocks, and the find_filename docstring includes an indented fence example. In the current implementation, the loop stops early because it checks the raw line with line.startswith("```") instead of checking the stripped line.

Steps to reproduce

Check out Aider main at commit 5dc9490bb35f9729ef2c95d00a19ccd30c26339c.

Add the following test inside TestUtils in tests/basic/test_editblock.py:

def test_find_filename_with_indented_fences(self):
    fence = ("```", "```")
    valid_fnames = ["dir/file3.py"]

    lines = ["  ```python", "file3.py", "  ```"]

    self.assertEqual(
        eb.find_filename(lines, fence, valid_fnames),
        "dir/file3.py",
    )

Run:

python -m pytest tests/basic/test_editblock.py -q

Expected behavior

find_filename should treat indented fenced markers the same way as non-indented fenced markers when looking back for a filename, and return:

dir/file3.py

Actual behavior

The added regression test fails because find_filename returns None:

FAILED tests/basic/test_editblock.py::TestUtils::test_find_filename_with_indented_fences
AssertionError: None != 'dir/file3.py'

1 failed, 25 passed in 1.32s

Impact

When an LLM returns a SEARCH/REPLACE block with slightly indented fenced markers, Aider may fail to recover the filename even though the filename is present and matches a known repo file. This can make an otherwise valid edit block fail with a missing filename error.

Root cause

Inside find_filename, each candidate line is first normalized by strip_filename(line, fence), which strips whitespace before checking for fences.

But the continuation check uses the raw line:

if not line.startswith(fence[0]) and not line.startswith(triple_backticks):
    break

For an indented fence like " ```", this condition becomes true and the loop breaks before it reaches the filename line.

Possible fix direction

Use a stripped line for the fence-continuation check:

stripped = line.strip()
if not stripped.startswith(fence[0]) and not stripped.startswith(triple_backticks):
    break

A regression test should cover both plain fenced blocks and indented fenced blocks.

Version and model info

Aider: 0.86.3.dev, main@5dc9490bb35f9729ef2c95d00a19ccd30c26339c
Python: focused unit-level reproduction
Operating system: macOS
Installation: source checkout
Edit format: search/replace
Model: not applicable; reproduced by directly invoking deterministic filename parsing code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions