{"record":{"id":"3125e3dcee0f8d14","repo":"SubtitleEdit/subtitleedit","slug":"moss-tts-crispasr-request-failed-the-connectio","errorCode":null,"errorMessage":"MOSS-TTS (CrispASR) request failed — the connection to the crispasr server was dropped.","messagePattern":"MOSS-TTS \\(CrispASR\\) request failed — the connection to the crispasr server was dropped\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ui/Features/Video/TextToSpeech/Engines/MossTtsCrispAsr.cs","lineNumber":476,"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 = $\"MOSS-TTS (CrispASR) request failed — Voice: {mossVoice}, 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                    ? \"MOSS-TTS (CrispASR) — the crispasr server crashed during synthesis.\"\n                    : \"MOSS-TTS (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 = $\"MOSS-TTS (CrispASR) server error {(int)response.StatusCode} {response.StatusCode} — \"\n                    + $\"Voice: {mossVoice}, Text: {text}, RequestJson: {body}, \"\n                    + $\"ResponseBody: {errorBody}, ServerLog: {serverLog}\"","sourceCodeStart":458,"sourceCodeEnd":494,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Features/Video/TextToSpeech/Engines/MossTtsCrispAsr.cs#L458-L494","documentation":"Thrown inside a catch(HttpRequestException) handler in MossTtsCrispAsr.Speak after HttpClient.PostAsync to the local crispasr server's /v1/audio/speech endpoint fails. The code checks _serverProcess?.HasExited and, because it is false (the else branch of the ternary), concludes the server process is still alive but the TCP connection was dropped mid-request. The original HttpRequestException is wrapped as the InnerException of the InvalidOperationException.","triggerScenarios":"POST to http://127.0.0.1:{port}/v1/audio/speech raises HttpRequestException while _serverProcess.HasExited is false. This happens when: the OS resets the TCP socket (RST) during a long synthesis; the server's internal HTTP handler dies but the process lingers; the HttpClient 30-minute timeout elapses; or antivirus/firewall interferes with loopback traffic.","commonSituations":"Synthesizing a very long subtitle line that exceeds the server's per-request memory or time budget; the server is CPU-thrashing on a low-RAM machine and the accept loop stalls; a second concurrent Speak call hit the server while it was already saturating all threads; Windows Defender or a corporate firewall briefly inspects and kills the loopback connection.","solutions":["Check the Tools log / error message for the 'Server log' tail — the server's own stderr often shows the OOM or CUDA error that caused it to stop accepting requests.","Retry the synthesis on a shorter text segment; split long subtitle lines and generate multiple clips.","Ensure the machine has enough free RAM/VRAM for the selected MOSS-TTS quant (Q4_K needs ~10.5 GB; F16 needs ~20.5 GB) — switch to a smaller quant in the model dropdown.","If it recurs, call StopServer() (or restart SE) to force a clean server respawn, since a zombie server process that stopped listening is still alive and blocks EnsureServerRunningAsync's MatchesCurrent check.","Add an exception for the SE folder / crispasr executable in antivirus real-time protection."],"exampleFix":"// before: a single long line that may exhaust the server\nawait engine.Speak(veryLongText, ...);\n\n// after: split and let the server recover between calls\nvar chunks = SplitLongText(veryLongText, maxChars: 500);\nforeach (var chunk in chunks)\n{\n    try { await engine.Speak(chunk, ...); }\n    catch (InvalidOperationException) when (serverMayHaveStalled)\n    {\n        MossTtsCrispAsr.StopServer(); // force respawn on next call\n        throw;\n    }\n}","handlingStrategy":"retry","validationCode":"// Before calling Speak, verify the server is still listening\nif (_serverProcess is { HasExited: false })\n{\n    var healthy = await ProbeHealthAsync(_serverPort, TimeSpan.FromSeconds(2), ct);\n    if (!healthy) { MossTtsCrispAsr.StopServer(); /* force respawn */ }\n}","typeGuard":"null","tryCatchPattern":"catch (InvalidOperationException ex) when (ex.InnerException is HttpRequestException)\n{\n    // The server process is alive but the connection dropped.\n    // Retry once after a short delay; if it fails again, StopServer to force a clean respawn.\n    if (attempt < maxRetries) { await Task.Delay(2000, ct); goto retry; }\n    MossTtsCrispAsr.StopServer();\n    throw;\n}","preventionTips":["Monitor server health via ProbeHealthAsync before batch synthesis runs.","Split long subtitle lines into <500-character chunks to avoid server-side timeouts.","Ensure the machine has sufficient RAM/VRAM for the selected quant before starting a batch."],"tags":["network","http","tts","moss-tts","crispasr","csharp"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}