invoke-ai/InvokeAI · error

Destination thumbnail already exists: {move.new_thumbnail_pa

Error message

Destination thumbnail already exists: {move.new_thumbnail_path}

What it means

When an image's existing thumbnail file is being moved, its destination thumbnail path must be free. preflight_moves raises FileExistsError if old_thumbnail_path exists but new_thumbnail_path already exists, guarding against clobbering another image's thumbnail.

Source

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

                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)
                continue
            message = f"Source image does not exist: {move.old_path}"
            self.create_error_move_job(move, message)
            self._logger.error(message)
            errors += 1
        return remaining_moves, errors

    def perform_filesystem_moves(self, job_id: int) -> None:
        self._set_job_state(job_id, "moving")
        self.complete_partial_filesystem_moves(job_id)

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Complete the earlier job via startup_recovery/complete_partial_filesystem_moves instead of re-planning
  2. Delete or rename the pre-existing destination thumbnail if it's stale
  3. Pick a different destination so thumbnail names don't collide
  4. Skip images whose thumbnails were already migrated in the caller

Example fix

// before
service.preflight_moves(moves)
// after
moves = [m for m in moves if not (m.old_thumbnail_path.exists() and m.new_thumbnail_path.exists())]
service.preflight_moves(moves)
Defensive patterns

Strategy: validation

Validate before calling

clashes = [m for m in moves if m.old_thumbnail_path.exists() and m.new_thumbnail_path.exists()]
if clashes:
    raise FileExistsError(f"destination thumbnails exist: {[str(m.new_thumbnail_path) for m in clashes]}")
service.preflight_moves(moves)

Type guard

def thumbnail_destination_free(move: PlannedImageMove) -> bool:
    return not (move.old_thumbnail_path.exists() and move.new_thumbnail_path.exists())

Try / catch

try:
    service.preflight_moves(moves)
except FileExistsError as e:
    if "Destination thumbnail" in str(e):
        clean_or_relocate_stale_thumbnail(e)
        service.preflight_moves(moves)
    else:
        raise

Prevention

When it happens

Trigger: Re-running a move whose thumbnails were already copied; two images whose thumbnail names collide and one already exists on disk; destination thumbnail folder seeded with same-named files.

Common situations: Interrupted prior move leaving thumbnails in place; shared thumbnail directory with name collisions; case-insensitive filesystems colliding thumbnail names.

Related errors


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