Aider-AI/aider · error · ValueError
Unexpected error applying action '{action.type}' to {action.
Error message
Unexpected error applying action '{action.type}' to {action.path}: {e} What it means
Second, broader wrapper in apply_edits: an exception that is not DiffError/OS-level (e.g. TypeError, IndexError, AttributeError) escaped while applying an action. It signals a bug or unexpected data shape in the apply path, not a normal patch mismatch.
Source
Thrown at aider/coders/patch_coder.py:638
# Ensure parent directory exists for target
target_path_obj.parent.mkdir(parents=True, exist_ok=True)
self.io.write_text(target_full_path, new_content)
# Remove original file *after* successful write to new location if moved
if action.move_path and full_path != target_full_path:
path_obj.unlink()
else:
# Should not happen
raise DiffError(f"Unknown action type encountered: {action.type}")
except (DiffError, FileNotFoundError, IOError, OSError) as e:
# Raise a ValueError to signal failure, consistent with other coders.
raise ValueError(f"Error applying action '{action.type}' to {action.path}: {e}")
except Exception as e:
# Catch unexpected errors during application
raise ValueError(
f"Unexpected error applying action '{action.type}' to {action.path}: {e}"
)
def _apply_update(self, text: str, action: PatchAction, path: str) -> str:
"""
Applies UPDATE chunks to the given text content.
Adapted from _get_updated_file in apply_patch.py.
"""
if action.type is not ActionType.UPDATE:
# Should not be called otherwise, but check for safety
raise DiffError("_apply_update called with non-update action")
orig_lines = text.splitlines() # Use splitlines to handle endings consistently
dest_lines: List[str] = []
current_orig_line_idx = 0 # Tracks index in orig_lines processed so far
# Sort chunks by their original index to apply them sequentially
sorted_chunks = sorted(action.chunks, key=lambda c: c.orig_index)View on GitHub (pinned to 5dc9490bb3)
Solutions
- Inspect the embedded exception message/type; if it's a TypeError/AttributeError, audit how the PatchAction and chunks were constructed
- Rebuild actions via the parser (parse a full patch text) instead of constructing them manually
- Report upstream if the actions came straight from parsed model output
Defensive patterns
Strategy: try-catch
Validate before calling
def actions_wellformed(actions) -> bool:
for a in actions:
if a.chunks is None or any(c is None for c in (a.chunks or [])):
return False
if a.type.name == "ADD" and not isinstance(a.new_content, str):
return False
return True Try / catch
try:
coder.apply_edits(edits)
except ValueError as e:
if str(e).startswith("Unexpected error"):
# capture full traceback — this is a bug, not a patch problem
log.exception("apply_edits internal failure")
raise Prevention
- Never construct chunks/actions with None fields; reparse from patch text instead
- Pin aider versions in automation so refactors don't shift internals
- Keep full traceback on unexpected errors to distinguish bugs from patch mismatches
When it happens
Trigger: Malformed chunks (None lines, negative indices) reaching _apply_update; unexpected None in new_content or chunks from hand-built PatchActions; regressions in helper functions raising arbitrary exceptions.
Common situations: Programmatic use of PatchCoder with custom-built actions; version mismatches after refactors; corrupt in-memory state after a failed parse is reused.
Related errors
- Error applying action '{action.type}' to {action.path}: {e}
- Delete File action missing path.
- Delete File Error - file not found: {path}
- Add File action missing path.
- Duplicate action for file: {path}
AI-assisted analysis of Aider-AI/aider@5dc9490bb3 (2026-08-15).
Data as JSON: /api/errors/1f5dd3229d928a59.
Report an issue: GitHub.