SubtitleEdit/subtitleedit · error · InvalidOperationException
OmniVoice (CrispASR) — the crispasr server crashed during sy
Error message
OmniVoice (CrispASR) — the crispasr server crashed during synthesis.
What it means
Thrown inside the catch(HttpRequestException) handler in OmniVoiceCrispAsr.Speak when the POST to the local crispasr omnivoice server fails AND _serverProcess?.HasExited is true (the 'died' branch). This means the server process crashed or was killed during the synthesis request, and the connection drop is a consequence of the process death. StopServerInternal is called to clean up before throwing.
Source
Thrown at src/ui/Features/Video/TextToSpeech/Engines/OmniVoiceCrispAsr.cs:469
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 = $"OmniVoice (CrispASR) request failed — Voice: {omniVoice}, Text: {text}, "
+ $"RequestJson: {body}, ServerExited: {died}, ServerLog: {serverLog}"
+ LaunchCmdSuffix(launchCommand);
Se.LogError(ex, failMsg);
Se.WriteToolsLog(failMsg);
throw new InvalidOperationException(
(died
? "OmniVoice (CrispASR) — the crispasr server crashed during synthesis."
: "OmniVoice (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 = $"OmniVoice (CrispASR) server error {(int)response.StatusCode} {response.StatusCode} — "
+ $"Voice: {omniVoice}, Text: {text}, RequestJson: {body}, "
+ $"ResponseBody: {errorBody}, ServerLog: {serverLog}"View on GitHub (pinned to 17a9f07487)
Solutions
- Read the 'Server log' in the exception — native crashes often log a signal (SIGSEGV, SIGABRT) or an assertion before dying.
- Re-import the reference voice WAV to ensure it is a valid 24 kHz mono file (ffmpeg conversion on import should handle this, but a manually-copied file may not).
- Ensure only the F16 tokenizer (omnivoice-tokenizer-f16.gguf) is in the models folder — remove any q8_0 tokenizer to prevent the codec-poisoning crash documented in the class remarks.
- Update GPU drivers and/or switch to a CPU build of crispasr to rule out a Metal/CUDA-specific crash.
- Switch to the Q4_K model quant to reduce memory pressure if the crash is OOM-related.
Example fix
// before — the server crashes silently during a long batch
await engine.Speak(text, ...);
// after — detect the crash and respawn with a fallback quant
try { await engine.Speak(text, ...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("crashed during synthesis"))
{
OmniVoiceCrispAsr.StopServer();
// next Speak() call will re-launch with fresh state
throw new TtsRetryableException(ex);
} Defensive patterns
Strategy: retry
Validate before calling
// Before synthesis, check server health and reference voice validity
if (_serverProcess is { HasExited: true })
OmniVoiceCrispAsr.StopServer(); // clear stale state for respawn
if (!string.IsNullOrEmpty(voicePath) && !File.Exists(voicePath))
throw new FileNotFoundException("Reference voice WAV missing: " + voicePath); Type guard
null
Try / catch
catch (InvalidOperationException ex) when (ex.Message.Contains("crashed during synthesis"))
{
// The server process died. OmniVoiceCrispAsr.StopServer() was already called internally.
// Retry once — EnsureServerRunningAsync will launch a fresh server.
if (attempt < maxRetries) { OmniVoiceCrispAsr.StopServer(); goto retry; }
throw;
} Prevention
- Ensure only the F16 tokenizer is in the models folder (remove q8_0 to prevent codec crashes).
- Re-import reference voice WAVs to guarantee valid 24 kHz mono format.
- Monitor VRAM usage during batch synthesis to catch OOM before it crashes the server.
When it happens
Trigger: HttpClient.PostAsync raises HttpRequestException, and the separate check _serverProcess.HasExited returns true. This happens when the omnivoice backend segfaults during inference, is killed by the OS OOM-killer, or hits a native crash (e.g., Metal/CUDA driver fault) mid-synthesis.
Common situations: Synthesizing with a corrupted reference voice WAV that causes a native crash in the codec encoder; VRAM exhaustion on a GPU that was also running other workloads; the q8_0 tokenizer was accidentally placed in the models folder and crispasr picked it up despite the --codec-model pin (the class doc warns this produces garbage then can crash); a macOS Metal driver panic on certain model layers.
Related errors
- OmniVoice (CrispASR) request failed — the connection to the
- OmniVoice (CrispASR) synthesis failed ({(int)response.Status
- MOSS-TTS (CrispASR) request failed — the connection to the c
- MOSS-TTS (CrispASR) synthesis failed ({(int)response.StatusC
- CrispASR executable not found. Install CrispASR via Video →
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/403aa386c5f12fbf.
Report an issue: GitHub.