unslothai/unsloth · warning · RuntimeError

sd-server job queue is full (HTTP 429).

Error message

sd-server job queue is full (HTTP 429).

What it means

The sd-server answered the img_gen submit with HTTP 429, meaning its internal job queue is full. This is backpressure, not a failure: the server intentionally caps concurrent queued jobs and tells the client to stop flooding it. The wrapper surfaces it distinctly so callers can throttle instead of treating it as a dead server.

Source

Thrown at studio/backend/core/inference/sd_cpp_server.py:466

        """
        # Already stopped with the cancel event set: report cancellation (route 409), not a generic "server died" 500.
        if self._stopped or not self.is_alive():
            if cancel_event is not None and cancel_event.is_set():
                raise SdCppCancelled("sd-server generation was cancelled.")
            raise RuntimeError("sd-server is not running.")

        self._step_listener = on_step
        job_id: Optional[str] = None
        try:
            # Submit -> 202 Accepted + job id.
            try:
                resp = self._client.post(
                    f"{self.base_url}{_IMG_GEN_PATH}", json = payload, timeout = submit_timeout
                )
            except (*_TRANSPORT_ERRORS, httpx.TimeoutException) as exc:
                raise RuntimeError(self._died_message("img_gen submit", exc)) from exc
            if resp.status_code == 429:
                raise RuntimeError("sd-server job queue is full (HTTP 429).")
            if resp.status_code not in (200, 202):
                raise RuntimeError(
                    f"sd-server img_gen submit -> {resp.status_code}: {resp.text[:500]}"
                )
            try:
                job = resp.json()
            except ValueError as exc:
                raise RuntimeError(
                    f"sd-server img_gen returned a non-JSON submit response: {exc}"
                ) from exc
            if not isinstance(job, dict):
                raise RuntimeError(
                    f"sd-server img_gen returned an unexpected submit response type: {type(job)}"
                )
            job_id = job.get("id")
            if not job_id:
                raise RuntimeError(f"sd-server img_gen returned no job id: {job}")

View on GitHub (pinned to 203007d190)

Solutions

  1. Wait for in-flight jobs to finish, then resubmit; respect 429 as a signal to throttle.
  2. Cap client-side concurrency to the server's queue size (or 1) with a semaphore.
  3. Batch multiple images into a single job (batch count) instead of many submitted jobs.

Example fix

# before
for prompt in prompts:
    threading.Thread(target=server.img_gen, args=(payload(prompt),)).start()
# after
sem = threading.Semaphore(1)
def gen(p):
    with sem:
        server.img_gen(payload(p))
Defensive patterns

Strategy: retry

Validate before calling

sem = threading.Semaphore(1)  # cap concurrent submits at the queue capacity
# with sem: server.img_gen(...)

Try / catch

try:
    blobs = server.img_gen(payload, ...)
except RuntimeError as e:
    if "queue is full" in str(e):
        time.sleep(2); blobs = server.img_gen(payload, ...)
    raise

Prevention

When it happens

Trigger: Submitting more concurrent img_gen jobs than the server's queue capacity while earlier jobs are still running — parallel batch fan-out from multiple threads or clients.

Common situations: A UI firing several generations at once; an automation script without a concurrency limiter; long-running jobs backing up the queue.

Understand the failure class

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/2787e9e52a15be21. Report an issue: GitHub.