{"record":{"id":"403aa386c5f12fbf","repo":"SubtitleEdit/subtitleedit","slug":"omnivoice-crispasr-the-crispasr-server-crashed","errorCode":null,"errorMessage":"OmniVoice (CrispASR) — the crispasr server crashed during synthesis.","messagePattern":"OmniVoice \\(CrispASR\\) — the crispasr server crashed during synthesis\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ui/Features/Video/TextToSpeech/Engines/OmniVoiceCrispAsr.cs","lineNumber":469,"sourceCode":"            response = await HttpClient.PostAsync($\"{ServerBaseUrl}/v1/audio/speech\", content, cancellationToken);\n        }\n        catch (HttpRequestException ex)\n        {\n            var serverLog = SnapshotServerLog();\n            var launchCommand = _serverLaunchCommand;\n            var died = _serverProcess?.HasExited == true;\n            if (died)\n            {\n                StopServerInternal();\n            }\n\n            var failMsg = $\"OmniVoice (CrispASR) request failed — Voice: {omniVoice}, Text: {text}, \"\n                + $\"RequestJson: {body}, ServerExited: {died}, ServerLog: {serverLog}\"\n                + LaunchCmdSuffix(launchCommand);\n            Se.LogError(ex, failMsg);\n            Se.WriteToolsLog(failMsg);\n\n            throw new InvalidOperationException(\n                (died\n                    ? \"OmniVoice (CrispASR) — the crispasr server crashed during synthesis.\"\n                    : \"OmniVoice (CrispASR) request failed — the connection to the crispasr server was dropped.\")\n                + (string.IsNullOrEmpty(serverLog) ? string.Empty : $\"{Environment.NewLine}Server log:{Environment.NewLine}{serverLog}\")\n                + LaunchCmdSuffix(launchCommand),\n                ex);\n        }\n\n        using (response)\n        {\n            if (!response.IsSuccessStatusCode)\n            {\n                var errorBody = await SafeReadErrorAsync(response, cancellationToken);\n                var serverLog = SnapshotServerLog();\n                var launchCommand = _serverLaunchCommand;\n                var errMsg = $\"OmniVoice (CrispASR) server error {(int)response.StatusCode} {response.StatusCode} — \"\n                    + $\"Voice: {omniVoice}, Text: {text}, RequestJson: {body}, \"\n                    + $\"ResponseBody: {errorBody}, ServerLog: {serverLog}\"","sourceCodeStart":451,"sourceCodeEnd":487,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Features/Video/TextToSpeech/Engines/OmniVoiceCrispAsr.cs#L451-L487","documentation":"Thrown inside the catch(HttpRequestException) handler in OmniVoiceCrispAsr.Speak when the POST to the local crispasr omnivoice server fails AND _serverProcess?.HasExited is true (the 'died' branch). This means the server process crashed or was killed during the synthesis request, and the connection drop is a consequence of the process death. StopServerInternal is called to clean up before throwing.","triggerScenarios":"HttpClient.PostAsync raises HttpRequestException, and the separate check _serverProcess.HasExited returns true. This happens when the omnivoice backend segfaults during inference, is killed by the OS OOM-killer, or hits a native crash (e.g., Metal/CUDA driver fault) mid-synthesis.","commonSituations":"Synthesizing with a corrupted reference voice WAV that causes a native crash in the codec encoder; VRAM exhaustion on a GPU that was also running other workloads; the q8_0 tokenizer was accidentally placed in the models folder and crispasr picked it up despite the --codec-model pin (the class doc warns this produces garbage then can crash); a macOS Metal driver panic on certain model layers.","solutions":["Read the 'Server log' in the exception — native crashes often log a signal (SIGSEGV, SIGABRT) or an assertion before dying.","Re-import the reference voice WAV to ensure it is a valid 24 kHz mono file (ffmpeg conversion on import should handle this, but a manually-copied file may not).","Ensure only the F16 tokenizer (omnivoice-tokenizer-f16.gguf) is in the models folder — remove any q8_0 tokenizer to prevent the codec-poisoning crash documented in the class remarks.","Update GPU drivers and/or switch to a CPU build of crispasr to rule out a Metal/CUDA-specific crash.","Switch to the Q4_K model quant to reduce memory pressure if the crash is OOM-related."],"exampleFix":"// before — the server crashes silently during a long batch\nawait engine.Speak(text, ...);\n\n// after — detect the crash and respawn with a fallback quant\ntry { await engine.Speak(text, ...); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"crashed during synthesis\"))\n{\n    OmniVoiceCrispAsr.StopServer();\n    // next Speak() call will re-launch with fresh state\n    throw new TtsRetryableException(ex);\n}","handlingStrategy":"retry","validationCode":"// Before synthesis, check server health and reference voice validity\nif (_serverProcess is { HasExited: true })\n    OmniVoiceCrispAsr.StopServer(); // clear stale state for respawn\nif (!string.IsNullOrEmpty(voicePath) && !File.Exists(voicePath))\n    throw new FileNotFoundException(\"Reference voice WAV missing: \" + voicePath);","typeGuard":"null","tryCatchPattern":"catch (InvalidOperationException ex) when (ex.Message.Contains(\"crashed during synthesis\"))\n{\n    // The server process died. OmniVoiceCrispAsr.StopServer() was already called internally.\n    // Retry once — EnsureServerRunningAsync will launch a fresh server.\n    if (attempt < maxRetries) { OmniVoiceCrispAsr.StopServer(); goto retry; }\n    throw;\n}","preventionTips":["Ensure only the F16 tokenizer is in the models folder (remove q8_0 to prevent codec crashes).","Re-import reference voice WAVs to guarantee valid 24 kHz mono format.","Monitor VRAM usage during batch synthesis to catch OOM before it crashes the server."],"tags":["process-crash","http","tts","omnivoice","crispasr","csharp"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}