{"record":{"id":"165721736734f226","repo":"SubtitleEdit/subtitleedit","slug":"failed-to-start-kokoro-tts-server","errorCode":null,"errorMessage":"Failed to start kokoro-tts-server","messagePattern":"Failed to start kokoro-tts-server","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ui/Features/Video/TextToSpeech/Engines/KokoroTtsCpp.cs","lineNumber":331,"sourceCode":"                // (relative path baked into the binary's default --vocab arg).\n                WorkingDirectory = GetSetFolder(),\n                FileName = exe,\n                UseShellExecute = false,\n                CreateNoWindow = true,\n                RedirectStandardError = true,\n                RedirectStandardOutput = true,\n            };\n            psi.ArgumentList.Add(\"-m\");\n            psi.ArgumentList.Add(modelPath);\n            psi.ArgumentList.Add(\"-V\");\n            psi.ArgumentList.Add(voicesPath);\n            psi.ArgumentList.Add(\"--host\");\n            psi.ArgumentList.Add(\"127.0.0.1\");\n            psi.ArgumentList.Add(\"--port\");\n            psi.ArgumentList.Add(port.ToString());\n\n            var process = Process.Start(psi)\n                ?? throw new InvalidOperationException(\"Failed to start kokoro-tts-server\");\n\n            Se.WriteToolsLog($\"Kokoro TTS server starting - PID: {process.Id}, \"\n                + $\"Cmd: {exe} {string.Join(' ', psi.ArgumentList)}\");\n\n            var stderrBuffer = new StringBuilder();\n            process.ErrorDataReceived += (_, e) =>\n            {\n                if (e.Data != null) lock (stderrBuffer) stderrBuffer.AppendLine(e.Data);\n            };\n            process.OutputDataReceived += (_, e) =>\n            {\n                if (e.Data != null) lock (stderrBuffer) stderrBuffer.AppendLine(e.Data);\n            };\n            process.BeginErrorReadLine();\n            process.BeginOutputReadLine();\n\n            _serverProcess = process;\n            _serverPort = port;","sourceCodeStart":313,"sourceCodeEnd":349,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Features/Video/TextToSpeech/Engines/KokoroTtsCpp.cs#L313-L349","documentation":"InvalidOperationException from KokoroTtsCpp.EnsureServerRunningAsync when `Process.Start(psi)` returns null. As with the other engines, modern .NET throws on spawn failure rather than returning null, so this is a defensive guard that is rarely hit in practice. If reached, the OS declined to spawn the configured kokoro-tts-server with the built argument list without a thrown exception.","triggerScenarios":"Effectively unreachable on current .NET; the realistic failures (missing exe → FileNotFoundException; permission/path issues → Win32Exception) throw before this line.","commonSituations":"Observed only on runtimes/shims returning null; otherwise a dead branch.","solutions":["Treat as 'spawn failed for unknown reason' — verify the exe path and permissions.","Run the exact command logged just after this throw by hand to surface the OS error.","Confirm GetExecutableFileName() is valid and executable.","Update the runtime if a genuine null return occurs."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (!File.Exists(exe)) throw new FileNotFoundException(\"kokoro exe missing\", exe);","typeGuard":null,"tryCatchPattern":"try { await kokoroEngine.Speak(...); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Failed to start kokoro-tts-server\"))\n{\n    ShowLaunchCommand(ex.Message); // reproduce manually\n}","preventionTips":["Pre-validate the exe path and permissions before Speak.","Use the logged launch command to reproduce OS-level spawn failures.","Keep the runtime current; a genuine null return is an upstream bug.","Check PATH/working-directory before retrying."],"tags":["kokoro","process-start","tts"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}