invoke-ai/InvokeAI · error

Duplicate destination path: {move.new_path}

Error message

Duplicate destination path: {move.new_path}

What it means

Two moves within the same planned batch must not target the same destination path. preflight_moves accumulates destinations in a set and raises ValueError on the second move targeting an already-claimed new_path, since only one source can occupy a destination.

Source

Thrown at invokeai/app/services/image_moves/image_moves_default.py:439

                    message,
                ),
            )
            return job_id

    def preflight_moves(self, moves: Sequence[PlannedImageMove]) -> None:
        destinations: set[Path] = set()
        thumbnail_destinations: set[Path] = set()
        for move in moves:
            if not move.old_path.exists():
                if not move.is_intermediate:
                    raise FileNotFoundError(f"Source image does not exist: {move.old_path}")
                continue
            if move.new_path.exists():
                raise FileExistsError(f"Destination image already exists: {move.new_path}")
            if move.old_path == move.new_path:
                raise ValueError(f"Old and new paths are identical for {move.image_name}")
            if move.new_path in destinations:
                raise ValueError(f"Duplicate destination path: {move.new_path}")
            destinations.add(move.new_path)
            if move.new_thumbnail_path in thumbnail_destinations:
                raise ValueError(f"Duplicate destination thumbnail path: {move.new_thumbnail_path}")
            thumbnail_destinations.add(move.new_thumbnail_path)
            if self._has_active_job_for_image(move.image_name):
                raise ValueError(f"Image {move.image_name} already has an active image move job")
            self._assert_same_filesystem(move.old_path, move.new_path)
            if move.old_thumbnail_path.exists():
                if move.new_thumbnail_path.exists():
                    raise FileExistsError(f"Destination thumbnail already exists: {move.new_thumbnail_path}")
                self._assert_same_filesystem(move.old_thumbnail_path, move.new_thumbnail_path)

    def _record_missing_source_errors(self, moves: Sequence[PlannedImageMove]) -> tuple[list[PlannedImageMove], int]:
        remaining_moves: list[PlannedImageMove] = []
        errors = 0
        for move in moves:
            if move.old_path.exists() or move.is_intermediate:
                remaining_moves.append(move)

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. De-duplicate or rename destination paths when building the moves list (e.g. append a numeric suffix on collision)
  2. Split the batch so colliding images move to different destinations
  3. Detect collisions up front in the caller using a set of new_path values

Example fix

// before
moves = [plan(img, dest) for img in images]  # may collide
// after
seen = set()
moves = [plan(img, uniquify(dest, seen)) for img in images]
service.preflight_moves(moves)
Defensive patterns

Strategy: validation

Validate before calling

dests = [m.new_path for m in moves]
dupes = {d for d in dests if dests.count(d) > 1}
if dupes:
    raise ValueError(f"duplicate destinations: {dupes}")
service.preflight_moves(moves)

Type guard

def destinations_unique(moves: Sequence[PlannedImageMove]) -> bool:
    return len({m.new_path for m in moves}) == len(moves)

Try / catch

try:
    service.preflight_moves(moves)
except ValueError as e:
    if "Duplicate destination path" in str(e):
        moves = uniquify_destinations(moves)  # suffix colliding names
        service.preflight_moves(moves)
    else:
        raise

Prevention

When it happens

Trigger: A batch where two images (e.g. duplicates or name-colliding images in different folders) are planned into the same target directory with the same filename; programmatic construction of PlannedImageMove lists that reuses a destination.

Common situations: Merging several subfolders into one folder where image names collide; copying images across boards with duplicate names into a shared target; generating moves without de-duplicating destinations.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/fdb7e771d092befb. Report an issue: GitHub.