SubtitleEdit/subtitleedit · error · InvalidOperationException
kokoro-tts-server exited during startup (code {NativeExitCod
Error message
kokoro-tts-server exited during startup (code {NativeExitCodeHelper.Describe(process.ExitCode)}). {hint} Output: {tail} What it means
InvalidOperationException from KokoroTtsCpp.EnsureServerRunningAsync when the kokoro-tts-server process exits before the first successful health probe. Distinctively, this one decodes the native exit code via NativeExitCodeHelper: an empty log + a 0xC00000xx code means the Windows loader killed the process before main (missing DLL, bad arch), and a human hint is appended. The described code and the last stderr tail are included.
Source
Thrown at src/ui/Features/Video/TextToSpeech/Engines/KokoroTtsCpp.cs:364
process.BeginOutputReadLine();
_serverProcess = process;
_serverPort = port;
HookProcessExitOnce();
var deadline = DateTime.UtcNow.AddSeconds(60);
while (DateTime.UtcNow < deadline)
{
ct.ThrowIfCancellationRequested();
if (process.HasExited)
{
var tail = SnapshotStderr(stderrBuffer);
_serverProcess = null;
_serverPort = 0;
// An empty tail plus a 0xC00000xx code means the loader killed it before main -
// NativeExitCodeHelper explains those instead of just printing the raw number.
var hint = NativeExitCodeHelper.GetHint(process.ExitCode, "Kokoro TTS", GetSetFolder());
throw new InvalidOperationException(
$"kokoro-tts-server exited during startup (code {NativeExitCodeHelper.Describe(process.ExitCode)})."
+ (hint == null ? string.Empty : " " + hint)
+ $" Output: {tail}");
}
if (await ProbeHealthAsync(port, TimeSpan.FromSeconds(1), ct))
{
return;
}
await Task.Delay(TimeSpan.FromMilliseconds(500), ct);
}
var lastOutput = SnapshotStderr(stderrBuffer);
StopServerInternal();
throw new TimeoutException(
$"kokoro-tts-server did not report healthy within 60s. Last output: {lastOutput}");
}
finally
{View on GitHub (pinned to 17a9f07487)
Solutions
- Read the hint from NativeExitCodeHelper — a 0xC0000135 means install the VC++ redistributable / required runtime.
- Read the `Output:` tail for the server's own startup error (e.g. `cannot find model`, `failed to open vocab`).
- Confirm the `-m` modelPath and `-V` voicesPath files exist and match the binary's expected format.
- Ensure the working directory (GetSetFolder) contains dict/vocab.txt the binary references.
- Install the matching architecture (x64) build of kokoro-tts-server.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: VC++ runtime present + assets in place
if (!HasVcRedist()) PromptInstallVcRedist();
if (!File.Exists(modelPath) || !File.Exists(voicesPath)) { PromptDownloadKokoroModels(); return; } Try / catch
try { await kokoroEngine.Speak(...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("exited during startup"))
{
// NativeExitCodeHelper hint explains loader kills (0xC0000135 etc.)
ShowDiagnostics(ex.Message); // includes hint + Output tail
} Prevention
- Install the Visual C++ redistributable on fresh Windows machines.
- Download the correct architecture (x64) of kokoro-tts-server.
- Keep dict/vocab.txt present in the working directory (GetSetFolder).
- Verify model/voices paths match the binary's expectations before startup.
When it happens
Trigger: Missing the Visual C++ runtime / required DLL (loader kills before main → 0xC0000135); running a 64-bit binary on a 32-bit OS or vice versa; model/voices path arguments invalid so the server exits immediately; the working directory (GetSetFolder) lacks the relative dict/vocab.txt the binary expects.
Common situations: Fresh Windows machine missing the VC++ redistributable; copied the binary without its dependency DLLs; wrong-architecture build downloaded; models folder moved so the `-m`/`-V` paths are wrong.
Related errors
- crispasr (f5-tts) exited during startup (code {exitCode}). O
- crispasr (indextts) exited during startup (code {exitCode}).
- Kokoro TTS synthesis failed ({(int)response.StatusCode}): {e
- Kokoro TTS server executable not found.
- Kokoro TTS model or voices file missing.
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/1adc079c7a511977.
Report an issue: GitHub.