{"record":{"id":"c03eb9e69f136037","repo":"Aider-AI/aider","slug":"add-change-for-action-path-has-no-content","errorCode":null,"errorMessage":"ADD change for {action.path} has no content","messagePattern":"ADD change for (.+?) has no content","errorType":"exception","errorClass":"DiffError","httpStatus":null,"severity":"error","filePath":"aider/coders/patch_coder.py","lineNumber":572,"sourceCode":"            return\n\n        # Group edits by original path? Not strictly needed if processed sequentially.\n\n        # Edits are now List[Tuple[str, PatchAction]]\n        for _path_tuple_element, action in edits:\n            # action is the PatchAction object\n            # action.path is the canonical path within the action logic\n            full_path = self.abs_root_path(action.path)\n            path_obj = pathlib.Path(full_path)\n\n            try:\n                if action.type == ActionType.ADD:\n                    # Check existence *before* writing\n                    if path_obj.exists():\n                        raise DiffError(f\"ADD Error: File already exists: {action.path}\")\n                    if action.new_content is None:\n                        # Parser should ensure this doesn't happen\n                        raise DiffError(f\"ADD change for {action.path} has no content\")\n\n                    self.io.tool_output(f\"Adding {action.path}\")\n                    path_obj.parent.mkdir(parents=True, exist_ok=True)\n                    # Ensure single trailing newline, matching reference behavior\n                    content_to_write = action.new_content\n                    if not content_to_write.endswith(\"\\n\"):\n                        content_to_write += \"\\n\"\n                    self.io.write_text(full_path, content_to_write)\n\n                elif action.type == ActionType.DELETE:\n                    self.io.tool_output(f\"Deleting {action.path}\")\n                    if not path_obj.exists():\n                        self.io.tool_warning(\n                            f\"DELETE Warning: File not found, skipping: {action.path}\"\n                        )\n                    else:\n                        path_obj.unlink()\n","sourceCodeStart":554,"sourceCodeEnd":590,"githubUrl":"https://github.com/Aider-AI/aider/blob/5dc9490bb35f9729ef2c95d00a19ccd30c26339c/aider/coders/patch_coder.py#L554-L590","documentation":"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.","triggerScenarios":"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.","commonSituations":"Custom automation wrapping PatchCoder; tests constructing actions by hand; code after a refactor that defaults new_content to None.","solutions":["Always set new_content (use \"\" for an empty file) when constructing ADD actions","If new_content is Optional in your code, default it to \"\" before apply_edits","Check for accidental mutation of action.new_content between parse and apply"],"exampleFix":"# before\nPatchAction(type=ActionType.ADD, path=\"a.txt\")\n\n# after\nPatchAction(type=ActionType.ADD, path=\"a.txt\", new_content=\"\")\n","handlingStrategy":"type-guard","validationCode":"def add_actions_have_content(actions) -> bool:\n    return all(a.new_content is not None for a in actions if a.type.name == \"ADD\")","typeGuard":"def is_valid_add_action(action) -> bool:\n    return (\n        action.type.name == \"ADD\"\n        and isinstance(action.path, str)\n        and action.path != \"\"\n        and isinstance(action.new_content, str)\n    )","tryCatchPattern":"try:\n    coder.apply_edits(edits)\nexcept ValueError as e:\n    if \"has no content\" in str(e):\n        edits = [a if a.type.name != \"ADD\" else replace(a, new_content=a.new_content or \"\") for a in edits]\n        coder.apply_edits(edits)\n    else:\n        raise","preventionTips":["Default new_content to '' when constructing ADD actions","Prefer generating actions via the parser instead of building PatchAction by hand","Assert invariants on programmatically built actions before apply"],"tags":["aider","patch","add","invariant"],"backgroundTag":null,"analyzedSha":"5dc9490bb35f9729ef2c95d00a19ccd30c26339c","analyzedAt":"2026-08-15T05:40:10.498Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}