unslothai/unsloth · error · SttAudioDecodeError

Could not decode the audio.

Error message

Could not decode the audio.

What it means

SttAudioDecodeError raised after a successful HTTP 2xx from whisper-server: the JSON payload's 'text' field is missing or not a string. Despite the decode-sounding message, this is a response-shape failure — the server answered but not with a usable transcription object.

Source

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

                    )
                payload = json.loads(response.read().decode("utf-8"))
        except (SttAudioDecodeError, SttEngineUnavailableError):
            raise
        except Exception as exc:
            # A cancel closes this socket deliberately, so it is not evidence of a broken
            # runtime and must not disable the engine.
            if cancel_event is None or not cancel_event.is_set():
                note_runtime_inference_failure(f"{type(exc).__name__}: {exc}")
            raise SttEngineUnavailableError(
                "The local transcription runtime did not answer the request. "
                "Transcription will use the Transformers engine from now on."
            ) from exc
        finally:
            cancel_done.set()
            connection.close()
        text = payload.get("text")
        if not isinstance(text, str):
            raise SttAudioDecodeError("Could not decode the audio.")
        # It served a transcription, so whatever failed earlier was transient.
        clear_runtime_inference_failure()
        # whisper.cpp joins segments with newlines; dictation wants one line.
        return " ".join(part.strip() for part in text.splitlines() if part.strip()).strip()


_sidecar: Optional[GgmlSttSidecar] = None


def get_ggml_stt_sidecar() -> GgmlSttSidecar:
    global _sidecar
    if _sidecar is None:
        _sidecar = GgmlSttSidecar()
    return _sidecar

View on GitHub (pinned to 203007d190)

Solutions

  1. Retry the transcription once — a transient malformed response is possible under load.
  2. Ensure the managed whisper.cpp runtime is current (`unsloth studio update`) so the response schema matches what the sidecar parses.
  3. If reproducible, capture the raw response body and verify it comes from whisper.cpp's server, not another local HTTP service.
Defensive patterns

Strategy: retry

Try / catch

try:
    result = sidecar.transcribe(audio, language=lang)
except SttAudioDecodeError as exc:
    if "Could not decode" in str(exc):
        result = retry_once_or_fallback(audio, lang)  # malformed server response
    else:
        raise

Prevention

When it happens

Trigger: _post_inference reads payload = json.loads(response.read()) and payload.get('text') is not a str — server returned an error body with 200, an empty object, or an unexpected schema from a different whisper-server build.

Common situations: A local process (not whisper.cpp) answered the probe and inference with a different JSON shape; whisper-server build drift changed its response schema; server returned an error envelope with status 200.

Related errors


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