invoke-ai/InvokeAI · warning · UnknownJobIDException

Unrecognized job

Error message

Unrecognized job

What it means

id_to_job() looks up the numeric job ID in the service's _jobs dict and wraps a KeyError as UnknownJobIDException('Unrecognized job'). IDs are only valid while their job object is retained by the service.

Source

Thrown at invokeai/app/services/download/download_default.py:287

        """List all the jobs."""
        return list(self._jobs.values())

    def prune_jobs(self) -> None:
        """Prune completed and errored queue items from the job list."""
        with self._lock:
            to_delete = set()
            for job_id, job in self._jobs.items():
                if job.in_terminal_state:
                    to_delete.add(job_id)
            for job_id in to_delete:
                del self._jobs[job_id]

    def id_to_job(self, id: int) -> DownloadJob:
        """Translate a job ID into a DownloadJob object."""
        try:
            return self._jobs[id]
        except KeyError as excp:
            raise UnknownJobIDException("Unrecognized job") from excp

    def cancel_job(self, job: DownloadJobBase) -> None:
        """
        Cancel the indicated job.

        If it is running it will be stopped.
        job.status will be set to DownloadJobStatus.CANCELLED
        """
        if job.status in [DownloadJobStatus.WAITING, DownloadJobStatus.RUNNING]:
            job.cancel()

    def cancel_all_jobs(self) -> None:
        """Cancel all jobs (those not in enqueued, running or paused state)."""
        for job in self._jobs.values():
            if not job.in_terminal_state:
                self.cancel_job(job)

    def wait_for_job(self, job: DownloadJobBase, timeout: int = 0) -> DownloadJobBase:

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Verify the ID came from a job created by the same running service instance (download()/submit_download_job() return value)
  2. Re-request the job list or re-submit the download if the service was restarted
  3. Catch UnknownJobIDException and treat it as 'job no longer tracked', resubmitting if needed
  4. Log the exact ID and compare against currently tracked jobs

Example fix

// before
job = service.id_to_job(job_id)
// after

try:
    job = service.id_to_job(job_id)
except UnknownJobIDException:
    job = service.download(url, dest)  # re-enqueue
Defensive patterns

Strategy: try-catch

Validate before calling

def job_id_known(service, job_id: int) -> bool:
    return job_id in getattr(service, "_jobs", {})

Type guard

def is_valid_job_id(v: object) -> bool:
    return isinstance(v, int) and v > 0

Try / catch

try:
    job = service.id_to_job(job_id)
except UnknownJobIDException:
    logger.info(f"job {job_id} no longer tracked; re-enqueueing")
    job = service.download(source, dest)

Prevention

When it happens

Trigger: Calling id_to_job(id) with an ID that was never created, a stale ID from a previous service instance, or an ID whose job was purged/completed and removed.

Common situations: Clients caching job IDs across app restarts, polling status for a job after service restart, or typo'd/misread ID values.

Related errors


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