{"record":{"id":"8b371a24f84e8b1e","repo":"SubtitleEdit/subtitleedit","slug":"crispasr-omnivoice-exited-during-startup-code","errorCode":null,"errorMessage":"crispasr (omnivoice) exited during startup (code {exitCode}). Output: {tail}{LaunchCmdSuffix}","messagePattern":"crispasr \\(omnivoice\\) exited during startup \\(code (.+?)\\)\\. Output: (.+?)(.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ui/Features/Video/TextToSpeech/Engines/OmniVoiceCrispAsr.cs","lineNumber":682,"sourceCode":"            HookProcessExitOnce();\n\n            // First-run auto-download pulls up to ~1.6 GB, so it gets a generous deadline.\n            var deadline = DateTime.UtcNow.AddMinutes(hasLocalModel ? 5 : 30);\n            while (DateTime.UtcNow < deadline)\n            {\n                ct.ThrowIfCancellationRequested();\n                if (process.HasExited)\n                {\n                    var tail = SnapshotServerLog();\n                    var exitCode = process.ExitCode;\n                    var exitedLaunchCommand = _serverLaunchCommand;\n                    _serverProcess = null;\n                    _serverPort = 0;\n                    _serverLaunchCommand = null;\n                    _serverModelKey = null;\n                    _serverVoicePath = null;\n                    _serverRefText = null;\n                    throw new InvalidOperationException(\n                        $\"crispasr (omnivoice) exited during startup (code {exitCode}). Output: {tail}\"\n                        + LaunchCmdSuffix(exitedLaunchCommand));\n                }\n                if (await ProbeHealthAsync(port, TimeSpan.FromSeconds(2), ct))\n                {\n                    return;\n                }\n                await Task.Delay(TimeSpan.FromSeconds(1), ct);\n            }\n\n            var lastOutput = SnapshotServerLog();\n            var timeoutLaunchCommand = _serverLaunchCommand;\n            StopServerInternal();\n            throw new TimeoutException(\n                $\"crispasr (omnivoice) did not report healthy within {(hasLocalModel ? 5 : 30)} minutes. Last output: {lastOutput}\"\n                + LaunchCmdSuffix(timeoutLaunchCommand));\n        }\n        finally","sourceCodeStart":664,"sourceCodeEnd":700,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Features/Video/TextToSpeech/Engines/OmniVoiceCrispAsr.cs#L664-L700","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the 'Output:' tail in the exception for the server's crash reason.","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.","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).","Manually run the 'Launch command' from the exception in a terminal to get the full untruncated error.","Update GPU drivers or test with a CPU build to isolate hardware-acceleration issues."],"exampleFix":"// before\nif (process.HasExited)\n{\n    throw new InvalidOperationException(\n        $\"crispasr (omnivoice) exited during startup (code {exitCode}). Output: {tail}\");\n}\n\n// after — add a hint for known exit codes (e.g., missing CUDA)\nvar hint = NativeExitCodeHelper.Format(\"OmniVoice (CrispASR)\", exitCode, GetSetFolder());\nthrow new InvalidOperationException(\n    $\"crispasr (omnivoice) exited during startup (code {exitCode}). {hint} Output: {tail}\");","handlingStrategy":"try-catch","validationCode":"// Pre-validate model and tokenizer files\nif (!OmniVoiceCrispAsr.AreModelsInstalled(modelKey))\n{\n    await ShowDownloadDialog(\"OmniVoice models are incomplete or corrupt.\");\n    return;\n}","typeGuard":"null","tryCatchPattern":"catch (InvalidOperationException ex) when (ex.Message.Contains(\"exited during startup\"))\n{\n    var tail = ExtractServerLog(ex.Message);\n    if (tail.Contains(\"unsupported type\")) // q8_0 tokenizer poisoning\n        await OfferTokenizerFix();\n    else if (tail.Contains(\"gguf\") || tail.Contains(\"magic\"))\n        await OfferModelRedownload();\n    else throw;\n}","preventionTips":["Ensure only omnivoice-tokenizer-f16.gguf is in the models folder.","Validate file sizes via IsValidLocalModelFile before launch.","Run the launch command manually to get full error output."],"tags":["process","startup","tts","omnivoice","crispasr","csharp"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}