{"record":{"id":"74b142f8dfed6f85","repo":"unslothai/unsloth","slug":"could-not-decode-the-audio","errorCode":null,"errorMessage":"Could not decode the audio.","messagePattern":"Could not decode the audio\\.","errorType":"exception","errorClass":"SttAudioDecodeError","httpStatus":400,"severity":"error","filePath":"studio/backend/core/inference/stt_ggml_sidecar.py","lineNumber":1211,"sourceCode":"                    )\n                payload = json.loads(response.read().decode(\"utf-8\"))\n        except (SttAudioDecodeError, SttEngineUnavailableError):\n            raise\n        except Exception as exc:\n            # A cancel closes this socket deliberately, so it is not evidence of a broken\n            # runtime and must not disable the engine.\n            if cancel_event is None or not cancel_event.is_set():\n                note_runtime_inference_failure(f\"{type(exc).__name__}: {exc}\")\n            raise SttEngineUnavailableError(\n                \"The local transcription runtime did not answer the request. \"\n                \"Transcription will use the Transformers engine from now on.\"\n            ) from exc\n        finally:\n            cancel_done.set()\n            connection.close()\n        text = payload.get(\"text\")\n        if not isinstance(text, str):\n            raise SttAudioDecodeError(\"Could not decode the audio.\")\n        # It served a transcription, so whatever failed earlier was transient.\n        clear_runtime_inference_failure()\n        # whisper.cpp joins segments with newlines; dictation wants one line.\n        return \" \".join(part.strip() for part in text.splitlines() if part.strip()).strip()\n\n\n_sidecar: Optional[GgmlSttSidecar] = None\n\n\ndef get_ggml_stt_sidecar() -> GgmlSttSidecar:\n    global _sidecar\n    if _sidecar is None:\n        _sidecar = GgmlSttSidecar()\n    return _sidecar\n","sourceCodeStart":1193,"sourceCodeEnd":1226,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/stt_ggml_sidecar.py#L1193-L1226","documentation":"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.","triggerScenarios":"_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.","commonSituations":"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.","solutions":["Retry the transcription once — a transient malformed response is possible under load.","Ensure the managed whisper.cpp runtime is current (`unsloth studio update`) so the response schema matches what the sidecar parses.","If reproducible, capture the raw response body and verify it comes from whisper.cpp's server, not another local HTTP service."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    result = sidecar.transcribe(audio, language=lang)\nexcept SttAudioDecodeError as exc:\n    if \"Could not decode\" in str(exc):\n        result = retry_once_or_fallback(audio, lang)  # malformed server response\n    else:\n        raise","preventionTips":["Keep whisper.cpp updated so the /inference JSON schema matches the parser.","Ensure nothing else can answer on the reserved 127.0.0.1 port.","Log the raw response body when this fires to distinguish schema drift from rogue responders."],"tags":["stt","ggml","response-schema","audio-decode","http"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}