SubtitleEdit/subtitleedit · error · InvalidOperationException
crispasr (moss-tts) exited during startup (code {exitCode}).
Error message
crispasr (moss-tts) exited during startup (code {exitCode}). Output: {tail}{LaunchCmdSuffix} What it means
InvalidOperationException thrown inside the EnsureServerRunningAsync startup-health loop when process.HasExited becomes true before the server responds to /health. The exit code and the last 2000 characters of the server's combined stdout/stderr log are captured and included in the message, along with the full launch command.
Source
Thrown at src/ui/Features/Video/TextToSpeech/Engines/MossTtsCrispAsr.cs:747
// First-run auto-download (backbone + codec is up to ~20.5 GB) needs a generous
// timeout; the 8B backbone also takes a while to load from disk.
var deadline = DateTime.UtcNow.AddMinutes(hasLocalModel ? 10 : 60);
while (DateTime.UtcNow < deadline)
{
ct.ThrowIfCancellationRequested();
if (process.HasExited)
{
var tail = SnapshotServerLog();
var exitCode = process.ExitCode;
var exitedLaunchCommand = _serverLaunchCommand;
_serverProcess = null;
_serverPort = 0;
_serverLaunchCommand = null;
_serverModelKey = null;
_serverVoicePath = null;
_serverRefText = null;
_serverLanguageArg = null;
throw new InvalidOperationException(
$"crispasr (moss-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 (moss-tts) did not report healthy within {(hasLocalModel ? 10 : 60)} minutes. Last output: {lastOutput}"
+ LaunchCmdSuffix(timeoutLaunchCommand));
}
finallyView on GitHub (pinned to 17a9f07487)
Solutions
- Read the 'Output:' section of the exception — it contains the server's stderr which names the exact failure (e.g., 'gguf: invalid magic', 'CUDA error: no kernel image').
- If the model file is corrupt, delete it from Se.CrispAsrFolder/models and re-download via the TTS download dialog (the ExpectedFileSizes guard may miss byte-correct corruption).
- Check the 'Launch command' suffix and manually run it in a terminal to reproduce and get the full error outside SE.
- Update GPU drivers or switch to a CPU/Vulkan build of crispasr if the error is CUDA/Metal related.
- Verify the reference voice WAV still exists at the path in the launch command.
Example fix
// before — the process exits silently during polling
if (process.HasExited)
{
throw new InvalidOperationException(
$"crispasr (moss-tts) exited during startup (code {exitCode}). Output: {tail}");
}
// after — also surface whether the exit was a known loader/OOM code
var hint = NativeExitCodeHelper.Format("MOSS-TTS (CrispASR)", exitCode, GetSetFolder());
throw new InvalidOperationException(
$"crispasr (moss-tts) exited during startup (code {exitCode}). {hint} Output: {tail}"); Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-validate model files before server launch
if (!MossTtsCrispAsr.AreModelsInstalled(modelKey))
{
await ShowDownloadDialog("MOSS-TTS models are incomplete.");
return;
} Type guard
null
Try / catch
catch (InvalidOperationException ex) when (ex.Message.Contains("exited during startup"))
{
// The exit code and server log tail are in the message.
// Parse them to decide: re-download models, update drivers, or report.
var tail = ExtractServerLog(ex.Message);
if (tail.Contains("invalid magic") || tail.Contains("gguf"))
await OfferModelRedownload();
else
throw;
} Prevention
- Validate model file sizes via IsValidLocalModelFile before launching the server.
- Keep GPU drivers up to date.
- Run the launch command manually in a terminal to get full untruncated output during debugging.
When it happens
Trigger: The crispasr process starts (Process.Start succeeds) but then exits within the startup polling window. Detected on the next loop iteration when process.HasExited is true. The server log tail reveals the cause: a corrupted/truncated GGUF model file, a missing codec companion, a CUDA/Metal init failure, a port conflict, or an invalid --voice path.
Common situations: A partially-downloaded model file (the ExpectedFileSizes check should catch truncation, but a corrupt-but-correct-size file slips through); GPU drivers missing or incompatible with the crispasr build; the --voice WAV was deleted between server-key computation and launch; a stale port was reused (FindFreeLoopbackPort has a TOCTOU window); the user's system locale causes a model-path parsing failure inside crispasr.
Related errors
- Failed to start crispasr (moss-tts)
- crispasr (moss-tts) did not report healthy within {10|60} mi
- crispasr (omnivoice) exited during startup (code {exitCode})
- MOSS-TTS (CrispASR) request failed — the connection to the c
- MOSS-TTS (CrispASR) synthesis failed ({(int)response.StatusC
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/55b2ef9eeb6f59a3.
Report an issue: GitHub.