SubtitleEdit/subtitleedit · error · InvalidOperationException
IndexTTS (CrispASR) synthesis failed ({(int)response.StatusC
Error message
IndexTTS (CrispASR) synthesis failed ({(int)response.StatusCode}): {errorBody} What it means
InvalidOperationException from IndexTtsCrispAsr.Speak when the POST to `/v1/audio/speech` returns a non-success HTTP status code. The server stayed up and answered, but with an error (4xx/5xx). The numeric code, the response body (via SafeReadErrorAsync), the server log, and the launch command are all captured and logged via Se.LogError before throwing.
Source
Thrown at src/ui/Features/Video/TextToSpeech/Engines/IndexTtsCrispAsr.cs:446
+ (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}"
+ LaunchCmdSuffix(launchCommand);
Se.LogError(errMsg);
Se.WriteToolsLog(errMsg);
throw new InvalidOperationException(
$"IndexTTS (CrispASR) synthesis failed ({(int)response.StatusCode}): {errorBody}"
+ (string.IsNullOrEmpty(serverLog) ? string.Empty : $"{Environment.NewLine}Server log:{Environment.NewLine}{serverLog}")
+ LaunchCmdSuffix(launchCommand));
}
await using var fileStream = File.Create(outputFileName);
await using var contentStream = await response.Content.ReadAsStreamAsync(cancellationToken);
await contentStream.CopyToAsync(fileStream, cancellationToken);
}
return new TtsResult(outputFileName, text);
}
private static string FormatLaunchCommand(string exe, System.Collections.ObjectModel.Collection<string> args)
{
static string Quote(string s) =>
!string.IsNullOrEmpty(s) && s.IndexOfAny(new[] { ' ', '\t' }) >= 0
? "\"" + s.Replace("\"", "\\\"") + "\""View on GitHub (pinned to 17a9f07487)
Solutions
- Read the `(status): errorBody` — the server's JSON error names the exact problem.
- HTTP 400 mentioning `voice`/path separators → ensure the payload omits the `voice` field (BuildSpeakPayload pattern).
- HTTP 500 → inspect the server log tail for the backend stack trace and retry; if reproducible, capture and report.
- Verify the CrispASR server version matches the payload schema the code expects.
- Confirm the `speed` value is within 0.25–4.0 (it is clamped, but a custom build may differ).
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate payload shape mirrors BuildSpeakPayload (no `voice` field)
Debug.Assert(!payload.ContainsKey("voice")); // path-traversal guard rejects it Try / catch
try { await indexEngine.Speak(...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("synthesis failed ("))
{
var status = ExtractStatusCode(ex.Message);
if (status == 400) WarnUser("Payload rejected by server — check voice field / schema.");
else if (status >= 500) { await Task.Delay(500, ct); await indexEngine.Speak(...); }
else ShowDiagnostics(ex.Message);
} Prevention
- Keep the payload built via BuildSpeakPayload (no per-request `voice` field) to dodge the 400 path-traversal guard.
- Pin the CrispASR server version the payload schema was authored against.
- Clamp `speed` to 0.25–4.0 (already done) and avoid unsupported formats.
- Unit-test the payload against the expected server schema on version bumps.
When it happens
Trigger: HTTP 400 from sending a `voice` field with path separators (the path-traversal guard) — the code deliberately omits `voice` to avoid this, so a 400 here means a payload regression; 500 from an internal backend exception during inference; 422 from unsupported input; 503 if the server is overloaded.
Common situations: A code change reintroduced the `voice` field (#12757 family bug); backend crashes-then-reports instead of exiting; unsupported sample rate / speed clamp violation; server version drift where the payload schema changed.
Related errors
- IndexTTS (CrispASR) — the crispasr server crashed during syn
- IndexTTS (CrispASR) request failed — the connection to the c
- CosyVoice3 (CrispASR) — the crispasr server crashed during s
- CosyVoice3 (CrispASR) synthesis failed ({(int)response.Statu
- F5-TTS (CrispASR) — the crispasr server crashed during synth
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/86368a2d60a1403f.
Report an issue: GitHub.