invoke-ai/InvokeAI · error · ImageMoveJobAlreadyRunning
An image move job is already active
Error message
An image move job is already active
What it means
Beyond the in-process future check, _start_background_operation consults _get_active_job_id (persisted/journaled active job). If an active job id exists and the requested operation is not 'recovery', it raises ImageMoveJobAlreadyRunning('An image move job is already active') — recovery is deliberately allowed to take over from a crashed run.
Source
Thrown at invokeai/app/services/image_moves/image_moves_default.py:148
if session_queue is None:
return
queue_status = session_queue.get_queue_status(DEFAULT_QUEUE_ID)
if queue_status.pending > 0 or queue_status.in_progress > 0:
raise ImageMoveQueueActive("Cannot start image move while queue work is active")
def _start_background_operation(
self,
operation: ImageMoveBackgroundOperation,
target,
require_idle_queue: bool = False,
) -> ImageMoveBackgroundStatus:
with self._future_lock:
self._refresh_finished_future_locked()
if self._future_operation is not None or (self._future is not None and not self._future.done()):
raise ImageMoveJobAlreadyRunning("An image move job is already running")
active_job_id = self._get_active_job_id()
if operation != "recovery" and active_job_id is not None:
raise ImageMoveJobAlreadyRunning("An image move job is already active")
self._last_background_error = None
self._future_operation = operation
try:
if require_idle_queue:
self._assert_no_active_queue_work()
future = self._executor.submit(self._run_background_operation, operation, target)
except Exception:
with self._future_lock:
self._future_operation = None
raise
with self._future_lock:
self._future = future
return self._build_background_status_locked()
def _run_background_operation(self, operation: ImageMoveBackgroundOperation, target) -> None:
try:View on GitHub (pinned to 0b6a024f2f)
Solutions
- Run start_background_recovery first to complete/commit the interrupted job and clear the active id
- Clear or commit the stale journal entry via the maintenance/recovery API
- Restart cleanly and complete recovery before scheduling new move operations
Example fix
// before service.start_background_move_all(target) # raises: active job id exists // after service.start_background_recovery() # finish interrupted job first # then, once recovery completes: service.start_background_move_all(target)
Defensive patterns
Strategy: try-catch
Validate before calling
def active_job_cleared(service) -> bool:
st = service.get_maintenance_status()
return not (st.is_maintenance_active or getattr(st, 'has_active_job', False))
if active_job_cleared(service):
service.start_background_move_all(target) Try / catch
from invokeai.app.services.image_moves.image_moves_common import ImageMoveJobAlreadyRunning
try:
service.start_background_move_all(target)
except ImageMoveJobAlreadyRunning:
service.start_background_recovery() # clear stale active job, then retry
service.start_background_move_all(target) Prevention
- After a crash/restart, always run recovery before new move jobs
- Monitor for uncommitted journals at startup
- Serialize move-job scheduling through one worker/queue in your tooling
When it happens
Trigger: Starting a new move while a journal/active-job record from a previous (possibly crashed) run exists; recovery interrupted by a non-recovery operation attempt with stale active job id.
Common situations: Server restarted mid-move leaving an uncommitted journal; previous job's active id never cleared due to a crash; attempting move_all before running recovery.
Related errors
- Cannot start image move while queue work is active
- An image move job is already running
- Cannot create image move job while another active image move
- Image {move.image_name} already has an active image move job
- Timeout exceeded
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/3ecf942d3507c053.
Report an issue: GitHub.