{"record":{"id":"cd149bbc14ee3031","repo":"SubtitleEdit/subtitleedit","slug":"omnivoice-crispasr-synthesis-failed-int-respo","errorCode":null,"errorMessage":"OmniVoice (CrispASR) synthesis failed ({(int)response.StatusCode}): {errorBody}{ServerLog}{LaunchCmdSuffix}","messagePattern":"OmniVoice \\(CrispASR\\) synthesis failed \\((.+?)\\): (.+?)(.+?)(.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ui/Features/Video/TextToSpeech/Engines/OmniVoiceCrispAsr.cs","lineNumber":491,"sourceCode":"                + (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}\"\n                    + LaunchCmdSuffix(launchCommand);\n                Se.LogError(errMsg);\n                Se.WriteToolsLog(errMsg);\n                throw new InvalidOperationException(\n                    $\"OmniVoice (CrispASR) synthesis failed ({(int)response.StatusCode}): {errorBody}\"\n                    + (string.IsNullOrEmpty(serverLog) ? string.Empty : $\"{Environment.NewLine}Server log:{Environment.NewLine}{serverLog}\")\n                    + LaunchCmdSuffix(launchCommand));\n            }\n\n            await using var fileStream = File.Create(outputFileName);\n            await using var contentStream = await response.Content.ReadAsStreamAsync(cancellationToken);\n            await contentStream.CopyToAsync(fileStream, cancellationToken);\n        }\n\n        return new TtsResult(outputFileName, text);\n    }\n\n    private static string TryReadRefText(string wavPath)\n    {\n        try\n        {\n            var sidecar = Path.ChangeExtension(wavPath, \".txt\");","sourceCodeStart":473,"sourceCodeEnd":509,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Features/Video/TextToSpeech/Engines/OmniVoiceCrispAsr.cs#L473-L509","documentation":"Thrown when the crispasr omnivoice server returns an HTTP response with a non-success status code from POST /v1/audio/speech. The response body is captured via SafeReadErrorAsync, and the message includes the numeric status code, the error body, the server log snapshot, and the launch command suffix.","triggerScenarios":"The HTTP call completes but response.IsSuccessStatusCode is false. For omnivoice, common causes: 400 for an unsupported language code (the per-request 'language' field requires v0.8.26+); 400 for empty input text; 500 when the backend's inference fails internally; 422 for a speed value the server rejects.","commonSituations":"Sending a language code that the installed crispasr version doesn't recognize (pre-v0.8.26 ignores it, but a version between v0.8.26 and the current pin may validate and reject); the speed setting was manually edited in settings to an out-of-range value; the voice WAV path contains characters the server's file loader rejects; a reference WAV that is stereo or wrong sample rate causes a codec error returned as 500.","solutions":["Read the errorBody in the exception — it is the server's structured error and identifies the exact field or condition that failed.","If the error is language-related, verify the crispasr binary is v0.8.26 or newer (check the .installed.sha256 sidecar) — the download service pins v0.8.28.","If cloning-related, re-import the reference WAV ensuring it is resampled to 24 kHz mono (the import path does this automatically, but a manually-copied file may not).","Reset the speed setting to 1.0 in SE settings if the value was manually edited.","Check the server log for stack traces that accompany 500 responses."],"exampleFix":"// before — language sent unconditionally\nif (!string.IsNullOrEmpty(languageArg))\n    payload[\"language\"] = languageArg;\n\n// after — guard against versions that reject unknown codes\nvar version = CrispAsrDownloadService.GetInstalledVersion();\nif (!string.IsNullOrEmpty(languageArg) && version >= new Version(0, 8, 26))\n    payload[\"language\"] = languageArg;","handlingStrategy":"try-catch","validationCode":"// Validate language support and input before the request\nif (string.IsNullOrWhiteSpace(text))\n    throw new ArgumentException(\"Input text must not be empty.\");\nvar version = CrispAsrDownloadService.GetInstalledVersion();\nif (!string.IsNullOrEmpty(languageArg) && version < new Version(0, 8, 26))\n    Se.WriteToolsLog(\"Warning: language field requires crispasr v0.8.26+; current: \" + version);","typeGuard":"null","tryCatchPattern":"catch (InvalidOperationException ex) when (ex.Message.Contains(\"synthesis failed (\"))\n{\n    var code = ExtractStatusCode(ex.Message);\n    if (code == 400 && ex.Message.Contains(\"language\"))\n    { /* strip the language field and retry, or warn the user */ }\n    else throw;\n}","preventionTips":["Ensure crispasr is v0.8.26+ before relying on per-request language selection.","Keep speed within 0.25–4.0.","Validate reference WAV is 24 kHz mono before using it for cloning."],"tags":["http","tts","omnivoice","crispasr","server-error","csharp"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}