unslothai/unsloth · warning · TimeoutError

deadline reached while pacing before {method} {_redact_url(u

Error message

deadline reached while pacing before {method} {_redact_url(url)}

What it means

Thrown (or surfaced via setModelsError/toast) by bailIfLoadInFlight in use-chat-model-runtime.ts:633-655 when a model load is requested while a different load (different id, GGUF variant, or native-path token) is already in flight. Same-pick duplicates are silently ignored; different picks set modelsError, throw when throwOnError was requested (the helper form of the selection), and toast. This centralizes the single-flight guard so every load entry point is covered.

Source

Thrown at scripts/virustotal_scan.py:402

        full socket timeout, so a loop that only checks afterwards can overrun the
        caller's budget by minutes and get the whole step killed before it writes
        a summary.
        """
        headers = {"x-apikey": self._api_key, "accept": "application/json"}
        if extra_headers:
            headers.update(extra_headers)

        backoff = self._request_interval if self._request_interval > 0 else 1.0
        last_error = ""
        for attempt in range(1, max_attempts + 1):
            if deadline is not None and self._clock() >= deadline:
                raise TimeoutError(f"deadline reached before {method} {_redact_url(url)}")
            self._throttle(deadline)
            # Re-check: pacing sleeps between the check above and the call below, so
            # without this a request could start after the deadline and then block
            # for the full socket timeout, overrunning the step's own budget.
            if deadline is not None and self._clock() >= deadline:
                raise TimeoutError(
                    f"deadline reached while pacing before {method} {_redact_url(url)}"
                )
            try:
                # Clamp the socket budget to what is left. Without this a call that
                # starts just before the deadline can still block for the full
                # socket timeout and consume the whole cushion the step relies on
                # to write its summary.
                socket_timeout = _SOCKET_TIMEOUT
                if deadline is not None:
                    socket_timeout = max(1.0, min(socket_timeout, deadline - self._clock()))
                status, payload = self._transport(method, url, headers, body, socket_timeout)
            except Exception as error:  # network layer, DNS, TLS, truncated read
                last_error = f"{type(error).__name__}: {error}"
                status, payload = 0, b""
            finally:
                self._last_request_at = self._clock()

            if status == 429:

View on GitHub (pinned to 203007d190)

Solutions

  1. Wait for the in-flight load to finish or cancel it (stop/cancel control) before requesting another.
  2. If the UI seems stuck 'loading' with no real load, reload the page or trigger a status refresh to clear the stale loadingModelRef/loadingModelPick state.
  3. Programmatic callers: pass throwOnError: true and catch this error to queue a retry once the current load completes.

Example fix

// before
void runtime.load(nextModel);

// after — honor the single-flight guard and queue
try {
  await runtime.load({ ...nextModel, throwOnError: true });
} catch (e) {
  if (e instanceof Error && e.message.startsWith("Another model is already loading")) {
    await waitForCurrentLoad();
    await runtime.load({ ...nextModel, throwOnError: true });
  } else throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

function canStartLoad(state: { loadingModel: unknown; loadingModelPick: unknown }): boolean {
  return !state.loadingModel && !state.loadingModelPick;
}

Type guard

function isLoadInFlightError(e: unknown): e is Error {
  return e instanceof Error && e.message.startsWith('Another model is already loading');
}

Try / catch

try {
  await loadModel({ ...selection, throwOnError: true });
} catch (error) {
  if (isLoadInFlightError(error)) {
    await waitForLoadSettled(); // poll status or subscribe to the store
    await loadModel({ ...selection, throwOnError: true });
  } else throw error;
}

Prevention

When it happens

Trigger: Calling load with selection A while loadingModelRef.current or loadingModelPick holds a different pick B — e.g. double-clicking two different model rows, switching model mid-load from the sidebar, or a GGUF variant change while another variant is still loading. The throw only happens for the object-form selection with throwOnError: true.

Common situations: Impatient users clicking several models in quick succession; automated scripts/staged configs firing loads while a previous load is slow (large GGUF); switching from a local model to another while the first is downloading.

Related errors


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