Aider-AI/aider · error · DiffError

ADD change for {action.path} has no content

Error message

ADD change for {action.path} has no content

What it means

Defensive guard in apply_edits(): an ADD PatchAction has new_content is None. The parser always sets new_content (even to empty string), so hitting this means the PatchAction was constructed manually or by a modified code path with missing content.

Source

Thrown at aider/coders/patch_coder.py:572

            return

        # Group edits by original path? Not strictly needed if processed sequentially.

        # Edits are now List[Tuple[str, PatchAction]]
        for _path_tuple_element, action in edits:
            # action is the PatchAction object
            # action.path is the canonical path within the action logic
            full_path = self.abs_root_path(action.path)
            path_obj = pathlib.Path(full_path)

            try:
                if action.type == ActionType.ADD:
                    # Check existence *before* writing
                    if path_obj.exists():
                        raise DiffError(f"ADD Error: File already exists: {action.path}")
                    if action.new_content is None:
                        # Parser should ensure this doesn't happen
                        raise DiffError(f"ADD change for {action.path} has no content")

                    self.io.tool_output(f"Adding {action.path}")
                    path_obj.parent.mkdir(parents=True, exist_ok=True)
                    # Ensure single trailing newline, matching reference behavior
                    content_to_write = action.new_content
                    if not content_to_write.endswith("\n"):
                        content_to_write += "\n"
                    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()

View on GitHub (pinned to 5dc9490bb3)

Solutions

  1. Always set new_content (use "" for an empty file) when constructing ADD actions
  2. If new_content is Optional in your code, default it to "" before apply_edits
  3. Check for accidental mutation of action.new_content between parse and apply

Example fix

# before
PatchAction(type=ActionType.ADD, path="a.txt")

# after
PatchAction(type=ActionType.ADD, path="a.txt", new_content="")
Defensive patterns

Strategy: type-guard

Validate before calling

def add_actions_have_content(actions) -> bool:
    return all(a.new_content is not None for a in actions if a.type.name == "ADD")

Type guard

def is_valid_add_action(action) -> bool:
    return (
        action.type.name == "ADD"
        and isinstance(action.path, str)
        and action.path != ""
        and isinstance(action.new_content, str)
    )

Try / catch

try:
    coder.apply_edits(edits)
except ValueError as e:
    if "has no content" in str(e):
        edits = [a if a.type.name != "ADD" else replace(a, new_content=a.new_content or "") for a in edits]
        coder.apply_edits(edits)
    else:
        raise

Prevention

When it happens

Trigger: Programmatically building PatchAction(type=ADD, path=...) without new_content and passing it to apply_edits; deserializing actions from JSON that dropped the new_content field.

Common situations: Custom automation wrapping PatchCoder; tests constructing actions by hand; code after a refactor that defaults new_content to None.

Related errors


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