SubtitleEdit/subtitleedit · error · InvalidOperationException

crispasr (omnivoice) exited during startup (code {exitCode})

Error message

crispasr (omnivoice) exited during startup (code {exitCode}). Output: {tail}{LaunchCmdSuffix}

What it means

InvalidOperationException thrown in the omnivoice server startup-health loop when the crispasr process exits before /health responds. The exit code and the last 2000 chars of the server log are captured. This is the omnivoice analogue of error 244.

Source

Thrown at src/ui/Features/Video/TextToSpeech/Engines/OmniVoiceCrispAsr.cs:682

            HookProcessExitOnce();

            // First-run auto-download pulls up to ~1.6 GB, so it gets a generous deadline.
            var deadline = DateTime.UtcNow.AddMinutes(hasLocalModel ? 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;
                    _serverLaunchCommand = null;
                    _serverModelKey = null;
                    _serverVoicePath = null;
                    _serverRefText = null;
                    throw new InvalidOperationException(
                        $"crispasr (omnivoice) 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 (omnivoice) did not report healthy within {(hasLocalModel ? 5 : 30)} minutes. Last output: {lastOutput}"
                + LaunchCmdSuffix(timeoutLaunchCommand));
        }
        finally

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Read the 'Output:' tail in the exception for the server's crash reason.
  2. Verify both required files exist with correct sizes: omnivoice-{quant}.gguf and omnivoice-tokenizer-f16.gguf in Se.CrispAsrFolder/models. Delete and re-download if corrupt.
  3. Ensure no omnivoice-tokenizer-q8_0.gguf is in the models folder — it can be picked up and causes codec crashes (documented in the class remarks).
  4. Manually run the 'Launch command' from the exception in a terminal to get the full untruncated error.
  5. Update GPU drivers or test with a CPU build to isolate hardware-acceleration issues.

Example fix

// before
if (process.HasExited)
{
    throw new InvalidOperationException(
        $"crispasr (omnivoice) exited during startup (code {exitCode}). Output: {tail}");
}

// after — add a hint for known exit codes (e.g., missing CUDA)
var hint = NativeExitCodeHelper.Format("OmniVoice (CrispASR)", exitCode, GetSetFolder());
throw new InvalidOperationException(
    $"crispasr (omnivoice) exited during startup (code {exitCode}). {hint} Output: {tail}");
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate model and tokenizer files
if (!OmniVoiceCrispAsr.AreModelsInstalled(modelKey))
{
    await ShowDownloadDialog("OmniVoice models are incomplete or corrupt.");
    return;
}

Type guard

null

Try / catch

catch (InvalidOperationException ex) when (ex.Message.Contains("exited during startup"))
{
    var tail = ExtractServerLog(ex.Message);
    if (tail.Contains("unsupported type")) // q8_0 tokenizer poisoning
        await OfferTokenizerFix();
    else if (tail.Contains("gguf") || tail.Contains("magic"))
        await OfferModelRedownload();
    else throw;
}

Prevention

When it happens

Trigger: Process.Start succeeds but the omnivoice backend process dies during model loading or server initialization. The server log tail typically shows the cause: a truncated GGUF, a CUDA init failure, a missing F16 tokenizer, or an invalid voice path.

Common situations: The omnivoice main GGUF is truncated or corrupt (the ExpectedFileSizes guard should prevent this, but byte-correct corruption is possible); the tokenizer GGUF is the q8_0 variant instead of F16 (crispasr loads it but crashes during codec init); GPU driver mismatch; the --voice reference WAV is malformed or zero-length.

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/8b371a24f84e8b1e. Report an issue: GitHub.