invoke-ai/InvokeAI · error

Source image does not exist: {move.old_path}

Error message

Source image does not exist: {move.old_path}

What it means

preflight_moves validates each planned move before any files are touched. If the source image file does not exist and the move is not marked intermediate, it raises FileNotFoundError naming the path. Intermediates are allowed to be missing (they may not have been written yet); regular images are not.

Source

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

                    move.old_subfolder,
                    move.new_subfolder,
                    int(move.is_intermediate),
                    str(move.old_path),
                    str(move.new_path),
                    str(move.old_thumbnail_path),
                    str(move.new_thumbnail_path),
                    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)

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Restore the missing file or delete the stale DB record, then re-plan
  2. Set is_intermediate on the PlannedImageMove if the file legitimately may not exist yet
  3. Verify the configured images root/path resolution matches where files actually live
  4. Filter out moves with nonexistent sources in the caller before planning

Example fix

// before
moves = [PlannedImageMove(image_name=n, old_path=p, new_path=q, is_intermediate=False)]
service.preflight_moves(moves)
// after
moves = [PlannedImageMove(image_name=n, old_path=p, new_path=q, is_intermediate=not p.exists())]
service.preflight_moves(moves)
Defensive patterns

Strategy: validation

Validate before calling

missing = [m for m in moves if not m.old_path.exists() and not m.is_intermediate]
if missing:
    raise FileNotFoundError(f"sources missing: {[str(m.old_path) for m in missing]}")
service.preflight_moves(moves)

Type guard

def source_exists(move: PlannedImageMove) -> bool:
    return move.is_intermediate or move.old_path.exists()

Try / catch

try:
    service.preflight_moves(moves)
except FileNotFoundError as e:
    reconcile_db_with_disk(str(e))  # repair stale records or restore files

Prevention

When it happens

Trigger: Planning a move for an image whose file was deleted from disk after being registered in the DB; wrong images root configured so paths don't resolve; calling preflight_moves/_plan_batch for an image on a detached/unmounted volume.

Common situations: Manual deletion or external sync tool removing files while InvokeAI's DB still lists them; misconfigured output/inputs directory; restoring the DB without restoring the file tree.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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