Aider-AI/aider · error · DiffError

Could not read file for UPDATE: {action.path}

Error message

Could not read file for UPDATE: {action.path}

What it means

Raised when an UPDATE target exists but io.read_text(full_path) returns None — the IO layer failed to read the file (encoding failure, permission issue, or unreadable path). Exists-but-unreadable is treated as an apply-time error rather than silently skipping.

Source

Thrown at aider/coders/patch_coder.py:598

                    self.io.write_text(full_path, content_to_write)

                elif action.type == ActionType.DELETE:
                    self.io.tool_output(f"Deleting {action.path}")
                    if not path_obj.exists():
                        self.io.tool_warning(
                            f"DELETE Warning: File not found, skipping: {action.path}"
                        )
                    else:
                        path_obj.unlink()

                elif action.type == ActionType.UPDATE:
                    if not path_obj.exists():
                        raise DiffError(f"UPDATE Error: File does not exist: {action.path}")

                    current_content = self.io.read_text(full_path)
                    if current_content is None:
                        # Should have been caught during parsing if file was needed
                        raise DiffError(f"Could not read file for UPDATE: {action.path}")

                    # Apply the update logic using the parsed chunks
                    new_content = self._apply_update(current_content, action, action.path)

                    target_full_path = (
                        self.abs_root_path(action.move_path) if action.move_path else full_path
                    )
                    target_path_obj = pathlib.Path(target_full_path)

                    if action.move_path:
                        self.io.tool_output(
                            f"Updating and moving {action.path} to {action.move_path}"
                        )
                        # Check if target exists before overwriting/moving
                        if target_path_obj.exists() and full_path != target_full_path:
                            self.io.tool_warning(
                                "UPDATE Warning: Target file for move already exists, overwriting:"
                                f" {action.move_path}"

View on GitHub (pinned to 5dc9490bb3)

Solutions

  1. Verify the file's encoding and aider's --encoding setting match
  2. Check read permissions on the file and parent directories
  3. Re-check the file still exists immediately before applying to rule out a race
Defensive patterns

Strategy: validation

Validate before calling

def update_targets_readable(root, actions) -> list[str]:
    bad = []
    for a in actions:
        if a.type.name == "UPDATE":
            p = os.path.join(root, a.path)
            try:
                with open(p, "r", encoding="utf-8") as f:
                    f.read()
            except (OSError, UnicodeDecodeError):
                bad.append(a.path)
    return bad

Try / catch

try:
    coder.apply_edits(edits)
except ValueError as e:
    if "Could not read file for UPDATE" in str(e):
        path = str(e).split("UPDATE: ", 1)[-1].strip()
        raise RuntimeError(f"unreadable file {path}: check encoding/permissions")
    raise

Prevention

When it happens

Trigger: Binary or non-declared-encoding files (read_text with strict encoding returns None); permission-denied on the file; file deleted between the exists() check and the read (TOCTOU).

Common situations: Patching a file with an encoding mismatch (e.g. latin-1 content read as utf-8); read-only mounts or sandboxed filesystems; races with external processes removing files.

Related errors


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