SubtitleEdit/subtitleedit · error · TimeoutException
crispasr (f5-tts) did not report healthy within {(hasLocalTa
Error message
crispasr (f5-tts) did not report healthy within {(hasLocalTalker ? 5 : 20)} minutes. Last output: {lastOutput}{LaunchCmdSuffix} What it means
Thrown as a TimeoutException when the f5-tts crispasr server starts and stays alive but never answers `/health` within the deadline — 5 minutes if a local talker GGUF is present, 20 minutes otherwise (to allow the ~953 MB first-run auto-download). The server process is stopped and the last 2000 chars of its log are attached.
Source
Thrown at src/ui/Features/Video/TextToSpeech/Engines/F5TtsCrispAsr.cs:651
_serverLaunchCommand = null;
_serverModelKey = null;
_serverVoicePath = null;
_serverRefText = null;
throw new InvalidOperationException(
$"crispasr (f5-tts) exited during startup (code {exitCode}). Output: {tail}"
+ LaunchCmdSuffix(exitedLaunchCommand));
}
if (await ProbeHealthAsync(port, TimeSpan.FromSeconds(2), ct))
{
return;
}
await Task.Delay(TimeSpan.FromSeconds(1), ct);
}
var lastOutput = SnapshotServerLog();
var timeoutLaunchCommand = _serverLaunchCommand;
StopServerInternal();
throw new TimeoutException(
$"crispasr (f5-tts) did not report healthy within {(hasLocalTalker ? 5 : 20)} minutes. Last output: {lastOutput}"
+ LaunchCmdSuffix(timeoutLaunchCommand));
}
finally
{
ServerLock.Release();
}
}
private static string SnapshotServerLog()
{
lock (_serverLog)
{
var s = _serverLog.ToString().TrimEnd();
return s.Length > 2000 ? s[^2000..] : s;
}
}
View on GitHub (pinned to 17a9f07487)
Solutions
- Check the `Last output:` tail — a still-downloading or still-loading server prints progress lines.
- If on first run, pre-stage the talker GGUF locally (place it at GetTalkerPath path) so the 5-minute deadline applies instead of 20.
- Ensure no firewall/VPN blocks loopback traffic to `127.0.0.1`.
- Close other GPU-heavy processes so the server can finish loading within the window.
- If the server is genuinely slow to init on your hardware, increase the deadline constant only after confirming the server eventually goes healthy when run manually.
Defensive patterns
Strategy: retry
Validate before calling
// Before Speak, sanity-check the model is present so the short 5-min deadline applies
if (!engine.HasLocalTalker(modelKey))
{
WarnUser("First run downloads ~953 MB and may need the full 20-min window on a slow link.");
} Try / catch
try { await f5Engine.Speak(...); }
catch (TimeoutException ex) when (ex.Message.Contains("did not report healthy"))
{
// Often a slow first-run download. Retry once after the user confirms the network/disk is free.
if (await ConfirmRetry("Server did not become healthy in time. Retry?"))
await f5Engine.Speak(...);
} Prevention
- Pre-download the talker GGUF so the 5-minute deadline applies.
- Keep loopback `127.0.0.1` traffic unblocked by firewall/VPN.
- Free GPU/CPU before a long TTS job so init completes in time.
- Pre-warm the engine with a tiny test utterance before batch runs.
When it happens
Trigger: The model download is slow/stalled on a poor network so the server never finishes loading; the server binds but `/health` hangs (deadlock in the backend); a host firewall blocks the loopback `127.0.0.1:port` health GET; the process is alive but pegged at 100% CPU initializing while the probe times out.
Common situations: Slow or proxy-filtered corporate network blocking the model CDN; a CrispASR version whose `/health` route changed; concurrent runs saturating the GPU so init never completes; large model on an underpowered machine.
Related errors
- crispasr (indextts) did not report healthy within {5|15} min
- crispasr (f5-tts) exited during startup (code {exitCode}). O
- kokoro-tts-server did not report healthy within 60s. Last ou
- crispasr (chatterbox) did not report healthy within 15 minut
- crispasr (cosyvoice3-tts) did not report healthy within {(al
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/3d03ac92e09d0e63.
Report an issue: GitHub.