unslothai/unsloth · warning · SttEngineUnavailableError

The local transcription runtime is being updated. Try dictat

Error message

The local transcription runtime is being updated. Try dictation again shortly.

What it means

Raised by GgmlSttSidecar._raise_if_update_in_progress when a whisper.cpp runtime update is mid-swap. The update_maintenance() context manager publishes this flag before replacing the managed whisper.cpp tree, so any load() or transcribe() call during that window is rejected instead of racing a partially swapped binary. It is a transient, deliberate unavailability rather than a defect.

Source

Thrown at studio/backend/core/inference/stt_ggml_sidecar.py:860

    ) -> None:
        """Release the resident model. ``wait=False`` skips a sidecar mid-request.

        `transcribe` holds ``_lock`` across the whole round trip, so a caller releasing
        engines it does not own must not block behind one. ``expected_model`` scopes the
        release to one model, compared under the lock.
        """
        if not self._lock.acquire(blocking = wait):
            return
        try:
            if not self._holds_expected_model(expected_model):
                return
            self._release_locked()
        finally:
            self._lock.release()

    def _raise_if_update_in_progress(self) -> None:
        if self._update_in_progress:
            raise SttEngineUnavailableError(
                "The local transcription runtime is being updated. Try dictation again shortly."
            )

    @contextmanager
    def update_maintenance(self) -> Iterator[bool]:
        """Block new loads while the managed whisper.cpp tree is replaced.

        The flag is published before waiting for an existing transcription to
        release ``_lock``. Holding that lock across the yielded installer phase
        prevents Windows from relocking the executable and prevents every host
        from starting a process against a partially swapped tree. The yielded
        value records whether a warm model had to be unloaded.
        """
        self._update_in_progress = True
        try:
            with self._lock:
                model_was_active = self._process_alive()
                self._release_locked()

View on GitHub (pinned to 203007d190)

Solutions

  1. Wait for the update to finish and retry the dictation request; the flag clears when update_maintenance() exits.
  2. Surface the 'try again shortly' message to the user instead of disabling the GGML engine — this error must not count as a runtime failure.
  3. If it persists, check that no update_maintenance() call deadlocked (e.g. an installer crashed while holding the flag) and restart Studio.
Defensive patterns

Strategy: retry

Validate before calling

if sidecar._update_in_progress:  # prefer a public accessor if exposed
    schedule_retry_later()
else:
    sidecar.load(model)

Try / catch

try:
    sidecar.load(model_id)
except SttEngineUnavailableError as exc:
    if "being updated" in str(exc):
        backoff_and_retry()  # transient maintenance window
    else:
        raise

Prevention

When it happens

Trigger: Calling load() or transcribe() on GgmlSttSidecar while another thread holds update_maintenance() (e.g. `unsloth studio update` or an engine auto-update is reinstalling whisper.cpp). Both the pre-lock check and the in-lock re-check after acquiring _lock raise it.

Common situations: User triggers a Studio engine update while a dictation hotkey/shortcut fires; an auto-updater runs in the background during a voice session; a queued transcription request lands during the installer phase of the maintenance window.

Related errors


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