invoke-ai/InvokeAI · error

Cannot create an image move job with no items

Error message

Cannot create an image move job with no items

What it means

create_move_job refuses to insert an image_subfolder_move_jobs row when the planned moves list is empty. An empty job would have no items to move, so the service treats it as a programming/caller mistake rather than a silent no-op. It is raised before any DB transaction begins.

Source

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

                    old_path=self.image_files.get_path(image_name, image_subfolder=old_subfolder),
                    new_path=self.image_files.get_path(image_name, image_subfolder=new_subfolder),
                    old_thumbnail_path=self.image_files.get_path(
                        image_name, thumbnail=True, image_subfolder=old_subfolder
                    ),
                    new_thumbnail_path=self.image_files.get_path(
                        image_name, thumbnail=True, image_subfolder=new_subfolder
                    ),
                )
            )
        errors = 0
        if record_missing_errors:
            moves, errors = self._record_missing_source_errors(moves)
        self.preflight_moves(moves)
        return moves, errors

    def create_move_job(self, moves: Sequence[PlannedImageMove]) -> int:
        if not moves:
            raise ValueError("Cannot create an image move job with no items")
        with self._db.transaction() as cursor:
            cursor.execute(
                """--sql
                SELECT 1
                FROM image_subfolder_move_jobs
                WHERE state NOT IN ('committed', 'error')
                LIMIT 1;
                """
            )
            if cursor.fetchone() is not None:
                raise ValueError("Cannot create image move job while another active image move job exists")
            cursor.execute("INSERT INTO image_subfolder_move_jobs (state) VALUES ('planned');")
            job_id = cast(int, cursor.lastrowid)
            cursor.executemany(
                """--sql
                INSERT INTO image_subfolder_move_items (
                    job_id,
                    image_name,

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Check that the moves list has at least one PlannedImageMove before calling create_move_job, or return early/raise a friendlier error in the caller
  2. In move_all_images, skip job creation when planning returns zero moves (optionally reporting 'nothing to move')
  3. Verify preflight/record_missing_source_errors filtering isn't unexpectedly dropping all moves

Example fix

// before
moves, errors = planner.plan(...)
job_id = service.create_move_job(moves)
// after
moves, errors = planner.plan(...)
if not moves:
    return  # or raise ValueError(f"nothing to move ({errors} errors)")
job_id = service.create_move_job(moves)
Defensive patterns

Strategy: validation

Validate before calling

if not moves:
    raise ValueError("refusing to create an image move job with no items")
service.create_move_job(moves)

Type guard

def has_moves(moves: Sequence[PlannedImageMove]) -> bool:
    return len(moves) > 0

Try / catch

try:
    job_id = service.create_move_job(moves)
except ValueError as e:
    if "no items" in str(e):
        log.info("nothing to move; skipping job creation")
        job_id = None
    else:
        raise

Prevention

When it happens

Trigger: Calling create_move_job([]) directly, or calling move_all_images/_plan_batch when _record_missing_source_errors filtered out every move (e.g. all sources already missing and counted as errors) so an empty list reaches this method.

Common situations: Batch scripts selecting an empty subfolder; UI invoking 'move all' on a folder with no images; after a previous run already removed/errored all candidate images so planning yields zero moves.

Related errors


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