{"record":{"id":"55b2ef9eeb6f59a3","repo":"SubtitleEdit/subtitleedit","slug":"crispasr-moss-tts-exited-during-startup-code-e","errorCode":null,"errorMessage":"crispasr (moss-tts) exited during startup (code {exitCode}). Output: {tail}{LaunchCmdSuffix}","messagePattern":"crispasr \\(moss-tts\\) exited during startup \\(code (.+?)\\)\\. Output: (.+?)(.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ui/Features/Video/TextToSpeech/Engines/MossTtsCrispAsr.cs","lineNumber":747,"sourceCode":"            // First-run auto-download (backbone + codec is up to ~20.5 GB) needs a generous\n            // timeout; the 8B backbone also takes a while to load from disk.\n            var deadline = DateTime.UtcNow.AddMinutes(hasLocalModel ? 10 : 60);\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                    _serverLanguageArg = null;\n                    throw new InvalidOperationException(\n                        $\"crispasr (moss-tts) 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 (moss-tts) did not report healthy within {(hasLocalModel ? 10 : 60)} minutes. Last output: {lastOutput}\"\n                + LaunchCmdSuffix(timeoutLaunchCommand));\n        }\n        finally","sourceCodeStart":729,"sourceCodeEnd":765,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Features/Video/TextToSpeech/Engines/MossTtsCrispAsr.cs#L729-L765","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — the process exits silently during polling\nif (process.HasExited)\n{\n    throw new InvalidOperationException(\n        $\"crispasr (moss-tts) exited during startup (code {exitCode}). Output: {tail}\");\n}\n\n// after — also surface whether the exit was a known loader/OOM code\nvar hint = NativeExitCodeHelper.Format(\"MOSS-TTS (CrispASR)\", exitCode, GetSetFolder());\nthrow new InvalidOperationException(\n    $\"crispasr (moss-tts) exited during startup (code {exitCode}). {hint} Output: {tail}\");","handlingStrategy":"try-catch","validationCode":"// Pre-validate model files before server launch\nif (!MossTtsCrispAsr.AreModelsInstalled(modelKey))\n{\n    await ShowDownloadDialog(\"MOSS-TTS models are incomplete.\");\n    return;\n}","typeGuard":"null","tryCatchPattern":"catch (InvalidOperationException ex) when (ex.Message.Contains(\"exited during startup\"))\n{\n    // The exit code and server log tail are in the message.\n    // Parse them to decide: re-download models, update drivers, or report.\n    var tail = ExtractServerLog(ex.Message);\n    if (tail.Contains(\"invalid magic\") || tail.Contains(\"gguf\"))\n        await OfferModelRedownload();\n    else\n        throw;\n}","preventionTips":["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."],"tags":["process","startup","tts","moss-tts","crispasr","csharp"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}