SubtitleEdit/subtitleedit · error · InvalidOperationException

IndexTTS (CrispASR) request failed — the connection to the c

Error message

IndexTTS (CrispASR) request failed — the connection to the crispasr server was dropped.

What it means

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.

Source

Thrown at src/ui/Features/Video/TextToSpeech/Engines/IndexTtsCrispAsr.cs:424

            response = await HttpClient.PostAsync($"{ServerBaseUrl}/v1/audio/speech", content, cancellationToken);
        }
        catch (HttpRequestException ex)
        {
            var serverLog = SnapshotServerLog();
            var launchCommand = _serverLaunchCommand;
            var died = _serverProcess?.HasExited == true;
            if (died)
            {
                StopServerInternal();
            }

            var failMsg = $"IndexTTS (CrispASR) request failed — Voice: {indexVoice}, Text: {text}, "
                + $"RequestJson: {body}, ServerExited: {died}, ServerLog: {serverLog}"
                + LaunchCmdSuffix(launchCommand);
            Se.LogError(ex, failMsg);
            Se.WriteToolsLog(failMsg);

            throw new InvalidOperationException(
                (died
                    ? "IndexTTS (CrispASR) — the crispasr server crashed during synthesis."
                    : "IndexTTS (CrispASR) request failed — the connection to the crispasr server was dropped.")
                + (string.IsNullOrEmpty(serverLog) ? string.Empty : $"{Environment.NewLine}Server log:{Environment.NewLine}{serverLog}")
                + LaunchCmdSuffix(launchCommand),
                ex);
        }

        using (response)
        {
            if (!response.IsSuccessStatusCode)
            {
                var errorBody = await SafeReadErrorAsync(response, cancellationToken);
                var serverLog = SnapshotServerLog();
                var launchCommand = _serverLaunchCommand;
                var errMsg = $"IndexTTS (CrispASR) server error {(int)response.StatusCode} {response.StatusCode} — "
                    + $"Voice: {indexVoice}, Text: {text}, RequestJson: {body}, "
                    + $"ResponseBody: {errorBody}, ServerLog: {serverLog}"

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Retry the synthesis — the server is still up and the drop is often transient.
  2. Check the appended `Server log:` for an in-server error that closed the socket without exiting.
  3. Ensure only one Speak call is in flight per server instance (the server restarts on voice/quant change, which can drop a concurrent request).
  4. Shorten very long input text into smaller chunks.
Defensive patterns

Strategy: retry

Validate before calling

// Best-effort: ensure no other Speak is restarting the server concurrently
if (engine.IsRestarting()) { await engine.WaitForServerIdleAsync(ct); }

Try / catch

try { await indexEngine.Speak(...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("connection to the crispasr server was dropped"))
{
    // Server still up; transient drop. Retry with small backoff.
    await Task.Delay(TimeSpan.FromMilliseconds(500), ct);
    await indexEngine.Speak(...);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/a43124dbc8197194. Report an issue: GitHub.