SubtitleEdit/subtitleedit · critical · InvalidOperationException
crispasr (qwen3-tts) exited during startup (code {exitCode})
Error message
crispasr (qwen3-tts) exited during startup (code {exitCode}). Output: {tail}{LaunchCmdSuffix} What it means
InvalidOperationException thrown during the crispasr startup health-wait when process.HasExited becomes true before /health succeeds. The message includes the raw exit code, the captured server log tail, and the launch command suffix so the user can reproduce the failing invocation manually.
Source
Thrown at src/ui/Features/Video/TextToSpeech/Engines/Qwen3TtsCrispAsr.cs:1025
_serverPort = port;
_serverModelKey = modelKey;
HookProcessExitOnce();
// First-run auto-download (~2 GB talker + ~986 MB codec) needs a generous timeout.
var deadline = DateTime.UtcNow.AddMinutes(hasLocalTalker && hasLocalCodec ? 5 : 30);
while (DateTime.UtcNow < deadline)
{
ct.ThrowIfCancellationRequested();
if (process.HasExited)
{
var tail = SnapshotServerLog();
var exitCode = process.ExitCode;
var exitedLaunchCommand = _serverLaunchCommand;
_serverProcess = null;
_serverPort = 0;
_serverModelKey = null;
_serverLaunchCommand = null;
throw new InvalidOperationException(
$"crispasr (qwen3-tts) exited during startup (code {exitCode}). Output: {tail}"
+ LaunchCmdSuffix(exitedLaunchCommand));
}
if (await ProbeHealthAsync(port, TimeSpan.FromSeconds(2), ct))
{
return;
}
await Task.Delay(TimeSpan.FromSeconds(1), ct);
}
var lastOutput = SnapshotServerLog();
var timeoutLaunchCommand = _serverLaunchCommand;
StopServerInternal();
throw new TimeoutException(
$"crispasr (qwen3-tts) did not report healthy within {(hasLocalTalker && hasLocalCodec ? 5 : 30)} minutes. Last output: {lastOutput}"
+ LaunchCmdSuffix(timeoutLaunchCommand));
}
finallyView on GitHub (pinned to 17a9f07487)
Solutions
- Read the appended Output tail — crispasr prints its fatal reason (e.g. 'failed to load talker', 'unknown backend').
- Run the printed Launch command manually in a terminal to see the full stderr.
- Confirm the talker and codec GGUFs are complete downloads or let --auto-download re-fetch.
- Match the --backend value to a backend that exists in this crispasr build.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: confirm model files and voice dir exist.
if (!Directory.Exists(GetSetVoicesFolder()))
throw new DirectoryNotFoundException("--voice-dir target missing.");
if (hasLocalTalker && !IsValidLocalModelFile(talker, GetTalkerFileName(modelKey)))
throw new FileNotFoundException("Talker model invalid", talker); Try / catch
try { await EnsureServerRunningAsync(modelKey, ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("exited during startup"))
{ await ShowServerStartupHelpAsync(ex.Message); throw; } Prevention
- Pre-stage complete talker/codec GGUFs or confirm network access for --auto-download.
- Match --backend to a backend compiled into this crispasr build.
- Run the printed launch command manually to capture full stderr.
When it happens
Trigger: Missing shared libraries abort crispasr before main; the talker/codec GGUF specified via -m is missing or corrupt; the --backend name doesn't match a compiled backend; --voice-dir points at a non-existent folder and crispasr aborts; GPU/driver incompatibility.
Common situations: First run before models are staged locally (the code falls back to --auto-download, which can still fail offline); a backend was compiled out of this crispasr build; a partial model download; driver/runtime mismatch.
Related errors
- crispasr (moss-tts) exited during startup (code {exitCode}).
- crispasr (moss-tts) did not report healthy within {10|60} mi
- crispasr (omnivoice) exited during startup (code {exitCode})
- crispasr (omnivoice) did not report healthy within {5|30} mi
- qwen3-tts-server exited during startup (code {NativeExitCode
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/636f424fd1dc5c33.
Report an issue: GitHub.