{"record":{"id":"a79529e3134e18b6","repo":"unslothai/unsloth","slug":"the-dictation-model-changed-while-this-recording-w","errorCode":null,"errorMessage":"The dictation model changed while this recording was being prepared. Try again.","messagePattern":"The dictation model changed while this recording was being prepared\\. Try again\\.","errorType":"http","errorClass":"SttModelBusyError","httpStatus":409,"severity":"warning","filePath":"studio/backend/core/inference/stt_mtmd_sidecar.py","lineNumber":1002,"sourceCode":"        # on CPU exactly as whisper.cpp and Transformers do. Refusing after a\n        # preload that succeeded only discarded the user's recording.\n        # Reject a missing model before decoding, matching the other sidecars.\n        self._ensure_model_downloaded(model_id)\n        decoded_audio = _decode_audio_bounded(audio, cancel_event)\n        if cancel_event is not None and cancel_event.is_set():\n            raise SttTranscriptionCancelledError(\"Transcription cancelled.\")\n        wav_bytes = _pcm_to_wav_bytes(decoded_audio)\n        audio_seconds = (len(decoded_audio) / _TARGET_SAMPLE_RATE) if len(decoded_audio) else None\n        self.load(model_id, request_cancel_event = cancel_event)\n        with self._lock:\n            port = self._port\n            if port is None or not self._process_alive():\n                raise SttUnavailableError(\"The dictation server is not running.\")\n            # Another client can switch models in the gap between that load\n            # returning and this lock, and the port read here would then be its\n            # server. Refuse rather than transcribe on the wrong model.\n            if self._model_id != model_id:\n                raise SttModelBusyError(\n                    \"The dictation model changed while this recording was being \"\n                    \"prepared. Try again.\"\n                )\n            # Long audio can outlast the keep-alive, and _post_transcribe runs\n            # outside the lock, so disarm the timer rather than let it kill\n            # llama-server mid-request and throw the dictation away.\n            self._active_requests += 1\n            self._cancel_idle_unload_locked()\n        try:\n            # Outside the lock: a held lock would block unload, including the\n            # one a training run performs, for the whole request timeout.\n            text = self._post_transcribe(\n                port, model_id, wav_bytes, audio_seconds, cancel_event = cancel_event\n            )\n            if cancel_event is not None and cancel_event.is_set():\n                raise SttTranscriptionCancelledError(\"Transcription cancelled.\")\n        except Exception:\n            if cancel_event is not None and cancel_event.is_set():","sourceCodeStart":984,"sourceCodeEnd":1020,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/stt_mtmd_sidecar.py#L984-L1020","documentation":"SttModelBusyError raised when, under _lock, self._model_id != model_id: another client switched the dictation model between this request's load() returning and the port being read. Transcribing would silently use the wrong model's server, so the request is refused instead.","triggerScenarios":"Client B calls load(other_model) and it completes while client A is between its load(model) and its locked port read in transcribe_bytes().","commonSituations":"Two clients dictating with different model selections; a settings change (model switch) landing during another window's in-flight recording.","solutions":["Retry the transcription — the retry loads/validates the current model again.","Use a single shared model selection across clients so switches cannot interleave.","Catch SttModelBusyError at the route and return 409 so the client knows to resubmit."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"```python\ntry:\n    return sidecar.transcribe_bytes(audio, model=model_id, cancel_event=ev)\nexcept SttModelBusyError:\n    return \"model changed, resubmit\", 409  # client retries with current model\n```","preventionTips":["Use one shared model selection across all clients to eliminate switch races.","Return 409 so the client knows a plain retry is safe.","Do not cache the model choice across a long audio preparation step."],"tags":["stt","model-switch","concurrency","race-condition"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}