Aider-AI/aider · error · DiffError

Error reading file {rel_path}: {e}

Error message

Error reading file {rel_path}: {e}

What it means

The IOError branch of PatchCoder's preload loop: reading the target file raised an IOError (other than FileNotFoundError) — permission denied, I/O error, or similar OS-level read failure. The original exception text is embedded in the DiffError message.

Source

Thrown at aider/coders/patch_coder.py:272

            start_index = 1  # Skip "*** Begin Patch"

        # Identify files needed for context lookups during parsing
        needed_paths = identify_files_needed(content)
        current_files: Dict[str, str] = {}
        for rel_path in needed_paths:
            abs_path = self.abs_root_path(rel_path)
            try:
                # Use io.read_text to handle potential errors/encodings
                file_content = self.io.read_text(abs_path)
                if file_content is None:
                    raise DiffError(
                        f"File referenced in patch not found or could not be read: {rel_path}"
                    )
                current_files[rel_path] = file_content
            except FileNotFoundError:
                raise DiffError(f"File referenced in patch not found: {rel_path}")
            except IOError as e:
                raise DiffError(f"Error reading file {rel_path}: {e}")

        try:
            # Parse the patch text using adapted logic
            patch_obj = self._parse_patch_text(lines, start_index, current_files)
            # Convert Patch object actions dict to a list of tuples (path, action)
            # for compatibility with the base Coder's prepare_to_edit method.
            results = []
            for path, action in patch_obj.actions.items():
                results.append((path, action))
            return results
        except DiffError as e:
            # Raise as ValueError for consistency with other coders' error handling
            raise ValueError(f"Error parsing patch content: {e}")
        except Exception as e:
            # Catch unexpected errors during parsing
            raise ValueError(f"Unexpected error parsing patch: {e}")

    def _parse_patch_text(

View on GitHub (pinned to 5dc9490bb3)

Solutions

  1. Check the embedded exception text ({e}) — it names the exact OS error (errno).
  2. Fix permissions/ownership: chmod/chown the file so the aider process can read it.
  3. Retry after releasing locks or remounting a stalled network filesystem.
  4. Run aider from a context with appropriate read access (correct user, container volume permissions).

Example fix

# shell fix for the reported path
chmod u+r src/locked_file.py
# or run aider as the file owner instead of another UID
Defensive patterns

Strategy: try-catch

Validate before calling

import os

def readable(rel_paths, root):
    problems = []
    for rel in rel_paths:
        p = os.path.join(root, rel)
        if os.path.exists(p) and not os.access(p, os.R_OK):
            problems.append(p)
    return problems  # chmod/chown these before applying the patch

Try / catch

try:
    coder.get_edits(patch_text)
except ValueError as e:
    msg = str(e)
    if msg.startswith("Error reading file"):
        fix_permissions_and_retry(msg)  # inspect embedded OS error, chmod, retry once
    else:
        raise

Prevention

When it happens

Trigger: io.read_text raises PermissionError/OSError (subclass of IOError) while preloading an '*** Update File:' path — unreadable permissions, file locked by another process, or a transient filesystem error (NFS/network mount).

Common situations: Files owned by another user or mode 000; editors/IDEs holding exclusive locks; flaky network mounts; containers running as a different UID than the file owner.

Related errors


AI-assisted analysis of Aider-AI/aider@5dc9490bb3 (2026-08-15). Data as JSON: /api/errors/fadf0aa2bac846b6. Report an issue: GitHub.