unslothai/unsloth · warning · SttModelBusyError

A transcription is still running on the current dictation mo

Error message

A transcription is still running on the current dictation model. Try again in a moment.

What it means

SttModelBusyError raised in _load_locked when a model switch is requested while self._active_requests > 0 and the current server process is alive. Switching would tear down a server that is mid-transcription, so the switch is refused instead — and it is refused before _release_locked(), so the user keeps the working server.

Source

Thrown at studio/backend/core/inference/stt_mtmd_sidecar.py:853

            # so a training start would otherwise see False and wait out the startup in
            # unload() instead of cancelling this load.
            cancel_event = (
                request_cancel_event if request_cancel_event is not None else threading.Event()
            )
            self._load_cancel_event = cancel_event
            self._load_owner_cancel_event = request_cancel_event
            self._loading = True
            released = False
            try:
                if cancel_event.is_set():
                    raise SttLoadCancelledError("Dictation model loading was cancelled.")
                # Before the release: a 409 for a model that is not downloaded
                # must not cost the user the server they were already using.
                model_path, mmproj_path = self._ensure_model_downloaded(model_id)
                # Only when there is a live server to protect: a request against
                # a server that already died must not block recovery.
                if self._active_requests and self._process_alive():
                    raise SttModelBusyError(
                        "A transcription is still running on the current dictation model. "
                        "Try again in a moment."
                    )
                self._release_locked()
                released = True
            finally:
                # Nothing started, so take the announcement back; past here the startup owns it.
                if not released:
                    self._loading = False
                    self._load_cancel_event = None
                    self._load_owner_cancel_event = None
            # Re-read last: _release_locked() reaps the old server, which can
            # take seconds, and training admission that already passed its own
            # check cannot come back to cancel this load. Publishing _loading
            # first covers the other order, so between them every training start
            # either cancels this load or is seen by it.
            training = _training_active()
        try:

View on GitHub (pinned to 203007d190)

Solutions

  1. Retry the model switch after the in-flight transcription finishes (usually seconds).
  2. Serialize model switches behind a queue so only one switch is attempted at a time.
  3. Keep a single model choice per session to avoid switch storms between clients.
Defensive patterns

Strategy: retry

Try / catch

```python
for attempt in range(3):
    try:
        sidecar.load(new_model_id)
        break
    except SttModelBusyError:
        time.sleep(1.0)  # in-flight transcription on the old model
else:
    return "model busy", 409
```

Prevention

When it happens

Trigger: Client A is transcribing on model X (active request in flight) while client B calls load(model Y) on the same sidecar instance.

Common situations: Two studio windows/tabs dictating with different models; a long recording still uploading while the user changes the voice model in settings; a preload racing a live transcription.

Related errors


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