{"record":{"id":"a43124dbc8197194","repo":"SubtitleEdit/subtitleedit","slug":"indextts-crispasr-request-failed-the-connectio","errorCode":null,"errorMessage":"IndexTTS (CrispASR) request failed — the connection to the crispasr server was dropped.","messagePattern":"IndexTTS \\(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/IndexTtsCrispAsr.cs","lineNumber":424,"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 = $\"IndexTTS (CrispASR) request failed — Voice: {indexVoice}, 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                    ? \"IndexTTS (CrispASR) — the crispasr server crashed during synthesis.\"\n                    : \"IndexTTS (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 = $\"IndexTTS (CrispASR) server error {(int)response.StatusCode} {response.StatusCode} — \"\n                    + $\"Voice: {indexVoice}, Text: {text}, RequestJson: {body}, \"\n                    + $\"ResponseBody: {errorBody}, ServerLog: {serverLog}\"","sourceCodeStart":406,"sourceCodeEnd":442,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Features/Video/TextToSpeech/Engines/IndexTtsCrispAsr.cs#L406-L442","documentation":"InvalidOperationException from the same HttpRequestException catch in IndexTtsCrispAsr.Speak, but the `died == false` branch: the POST failed with an HttpRequestException while the server process is still running. The connection was dropped or never established, but the server did not exit. The inner exception is chained and the server log + launch command are appended for diagnosis.","triggerScenarios":"Transient loopback socket reset; the server is alive but the listening thread was briefly unresponsive (e.g. mid-GC or model swap); a host firewall intermittently dropping connections; the request exceeded an in-server timeout and the socket was closed; rapid concurrent requests saturating the server's accept backlog.","commonSituations":"Network/firewall flakiness on loopback; very long input text where the server closes the keep-alive before responding; another Speak call restarted the server (voice/quant changed) while this one was in flight.","solutions":["Retry the synthesis — the server is still up and the drop is often transient.","Check the appended `Server log:` for an in-server error that closed the socket without exiting.","Ensure only one Speak call is in flight per server instance (the server restarts on voice/quant change, which can drop a concurrent request).","Shorten very long input text into smaller chunks."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Best-effort: ensure no other Speak is restarting the server concurrently\nif (engine.IsRestarting()) { await engine.WaitForServerIdleAsync(ct); }","typeGuard":null,"tryCatchPattern":"try { await indexEngine.Speak(...); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"connection to the crispasr server was dropped\"))\n{\n    // Server still up; transient drop. Retry with small backoff.\n    await Task.Delay(TimeSpan.FromMilliseconds(500), ct);\n    await indexEngine.Speak(...);\n}","preventionTips":["Serialize Speak calls per server instance (the server restarts on voice/quant change).","Chunk long input to avoid server keep-alive timeouts closing the socket.","Retry once on transient connection drops before surfacing to the user.","Log the launch command so dropped connections can be reproduced manually."],"tags":["indextts","crispasr","http","connection-dropped","tts","synthesis"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}