{"record":{"id":"dbb99de865ab164c","repo":"SubtitleEdit/subtitleedit","slug":"kokoro-tts-server-did-not-report-healthy-within-60","errorCode":null,"errorMessage":"kokoro-tts-server did not report healthy within 60s. Last output: {lastOutput}","messagePattern":"kokoro-tts-server did not report healthy within 60s\\. Last output: (.+?)","errorType":"exception","errorClass":"TimeoutException","httpStatus":null,"severity":"error","filePath":"src/ui/Features/Video/TextToSpeech/Engines/KokoroTtsCpp.cs","lineNumber":378,"sourceCode":"                    _serverPort = 0;\n                    // An empty tail plus a 0xC00000xx code means the loader killed it before main -\n                    // NativeExitCodeHelper explains those instead of just printing the raw number.\n                    var hint = NativeExitCodeHelper.GetHint(process.ExitCode, \"Kokoro TTS\", GetSetFolder());\n                    throw new InvalidOperationException(\n                        $\"kokoro-tts-server exited during startup (code {NativeExitCodeHelper.Describe(process.ExitCode)}).\"\n                        + (hint == null ? string.Empty : \" \" + hint)\n                        + $\" Output: {tail}\");\n                }\n                if (await ProbeHealthAsync(port, TimeSpan.FromSeconds(1), ct))\n                {\n                    return;\n                }\n                await Task.Delay(TimeSpan.FromMilliseconds(500), ct);\n            }\n\n            var lastOutput = SnapshotStderr(stderrBuffer);\n            StopServerInternal();\n            throw new TimeoutException(\n                $\"kokoro-tts-server did not report healthy within 60s. Last output: {lastOutput}\");\n        }\n        finally\n        {\n            ServerLock.Release();\n        }\n    }\n\n    private static string SnapshotStderr(StringBuilder buffer)\n    {\n        lock (buffer)\n        {\n            var s = buffer.ToString().TrimEnd();\n            return s.Length > 2000 ? s[^2000..] : s;\n        }\n    }\n\n    private static async Task<bool> ProbeHealthAsync(int port, TimeSpan timeout, CancellationToken ct)","sourceCodeStart":360,"sourceCodeEnd":396,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Features/Video/TextToSpeech/Engines/KokoroTtsCpp.cs#L360-L396","documentation":"TimeoutException from KokoroTtsCpp.EnsureServerRunningAsync when the kokoro-tts-server starts and stays alive but does not answer `/health` within 60 seconds. The server is stopped and the last 2000 chars of combined stdout/stderr are attached. Kokoro has no large auto-download, so the deadline is a flat 60s — slower hardware or heavy model load can exhaust it.","triggerScenarios":"The server is alive but `/health` is unresponsive (slow model mmap load on a cold disk); loopback firewall blocking the health GET; the server is waiting on a missing dependency and hung (not exited); concurrent disk/CPU contention.","commonSituations":"First run with a cold OS file cache so model load is slow; antivirus scanning the model on open; slow HDD; heavy background I/O.","solutions":["Inspect `Last output:` for the server's load progress.","Run the server manually to measure real init time; if it consistently exceeds 60s on your hardware, pre-warm the model.","Disable AV scanning of the models folder.","Move models to faster storage (SSD).","Free CPU/disk contention during startup."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-warm the model so the 60s window is enough on slow disks\nawait kokoroEngine.PreWarmAsync(ct); // touch/mmap the model once","typeGuard":null,"tryCatchPattern":"try { await kokoroEngine.Speak(...); }\ncatch (TimeoutException ex) when (ex.Message.Contains(\"did not report healthy within 60s\"))\n{\n    if (await ConfirmRetry()) await kokoroEngine.Speak(...);\n}","preventionTips":["Pre-warm the engine with a tiny utterance before batch jobs.","Exclude the models folder from AV on-open scanning.","Keep models on SSD.","Free CPU/disk contention during the first startup."],"tags":["kokoro","health-check","timeout","server","tts"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}