{"record":{"id":"4ad47ddaa3ab78f2","repo":"invoke-ai/InvokeAI","slug":"old-and-new-paths-are-identical-for-move-image-na","errorCode":null,"errorMessage":"Old and new paths are identical for {move.image_name}","messagePattern":"Old and new paths are identical for (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"invokeai/app/services/image_moves/image_moves_default.py","lineNumber":437,"sourceCode":"                    str(move.old_thumbnail_path),\n                    str(move.new_thumbnail_path),\n                    message,\n                ),\n            )\n            return job_id\n\n    def preflight_moves(self, moves: Sequence[PlannedImageMove]) -> None:\n        destinations: set[Path] = set()\n        thumbnail_destinations: set[Path] = set()\n        for move in moves:\n            if not move.old_path.exists():\n                if not move.is_intermediate:\n                    raise FileNotFoundError(f\"Source image does not exist: {move.old_path}\")\n                continue\n            if move.new_path.exists():\n                raise FileExistsError(f\"Destination image already exists: {move.new_path}\")\n            if move.old_path == move.new_path:\n                raise ValueError(f\"Old and new paths are identical for {move.image_name}\")\n            if move.new_path in destinations:\n                raise ValueError(f\"Duplicate destination path: {move.new_path}\")\n            destinations.add(move.new_path)\n            if move.new_thumbnail_path in thumbnail_destinations:\n                raise ValueError(f\"Duplicate destination thumbnail path: {move.new_thumbnail_path}\")\n            thumbnail_destinations.add(move.new_thumbnail_path)\n            if self._has_active_job_for_image(move.image_name):\n                raise ValueError(f\"Image {move.image_name} already has an active image move job\")\n            self._assert_same_filesystem(move.old_path, move.new_path)\n            if move.old_thumbnail_path.exists():\n                if move.new_thumbnail_path.exists():\n                    raise FileExistsError(f\"Destination thumbnail already exists: {move.new_thumbnail_path}\")\n                self._assert_same_filesystem(move.old_thumbnail_path, move.new_thumbnail_path)\n\n    def _record_missing_source_errors(self, moves: Sequence[PlannedImageMove]) -> tuple[list[PlannedImageMove], int]:\n        remaining_moves: list[PlannedImageMove] = []\n        errors = 0\n        for move in moves:","sourceCodeStart":419,"sourceCodeEnd":455,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/services/image_moves/image_moves_default.py#L419-L455","documentation":"A move where old_path == new_path is a no-op and likely a naming/planning bug, so preflight_moves raises ValueError identifying the offending image_name. It only fires when the source exists (checked earlier) and the path isn't already taken by another file check ordering.","triggerScenarios":"Computing a destination subfolder that resolves to the image's current location (e.g. moving to the same folder with the same name); passing identical old/new paths by mistake when constructing PlannedImageMove; path normalization differences resolved to the same path.","commonSituations":"UI allowing the user to select the image's current folder as the target; scripts that build target paths with empty suffix components; symlinks or relative paths that resolve identically.","solutions":["In the caller, skip or filter moves whose resolved old_path equals new_path (treat as success/no-op)","Fix destination path computation so the target differs from the source","Normalize both paths before planning and drop identity moves"],"exampleFix":"// before\nservice.preflight_moves(moves)\n// after\nmoves = [m for m in moves if m.old_path != m.new_path]\nservice.preflight_moves(moves)","handlingStrategy":"validation","validationCode":"identical = [m for m in moves if m.old_path == m.new_path]\nif identical:\n    raise ValueError(f\"identity moves: {[m.image_name for m in identical]}\")\nservice.preflight_moves(moves)","typeGuard":"def is_real_move(move: PlannedImageMove) -> bool:\n    return move.old_path != move.new_path","tryCatchPattern":"try:\n    service.preflight_moves(moves)\nexcept ValueError as e:\n    if \"identical\" in str(e):\n        moves = [m for m in moves if m.old_path != m.new_path]\n        service.preflight_moves(moves)\n    else:\n        raise","preventionTips":["Filter identity moves at planning time and treat them as no-ops","Normalize (resolve) both paths before comparison","Validate user-chosen target folders differ from the current one"],"tags":["validation","image-move","preflight","path-resolution"],"backgroundTag":"invalid-move-operation","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}