SubtitleEdit/subtitleedit · error · TimeoutException

crispasr (omnivoice) did not report healthy within {5|30} mi

Error message

crispasr (omnivoice) did not report healthy within {5|30} minutes. Last output: {lastOutput}{LaunchCmdSuffix}

What it means

TimeoutException thrown when the crispasr omnivoice server stays alive but never responds to /health within the deadline (5 minutes for a locally-staged model, 30 minutes if first-run auto-download is needed). StopServerInternal is called before throwing. This is the omnivoice analogue of error 245, with shorter deadlines because omnivoice models are smaller (~1-1.6 GB vs ~10-20 GB for MOSS-TTS).

Source

Thrown at src/ui/Features/Video/TextToSpeech/Engines/OmniVoiceCrispAsr.cs:696

                    _serverLaunchCommand = null;
                    _serverModelKey = null;
                    _serverVoicePath = null;
                    _serverRefText = null;
                    throw new InvalidOperationException(
                        $"crispasr (omnivoice) 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 (omnivoice) did not report healthy within {(hasLocalModel ? 5 : 30)} 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

  1. Check 'Last output' — if it shows download progress, pre-download the model GGUF and tokenizer manually into Se.CrispAsrFolder/models.
  2. Switch to Q4_K (~1 GB) to reduce both download and load time.
  3. Ensure the models are on local storage (SSD preferred), not a network mount.
  4. Verify the installed crispasr version exposes GET /health (older builds may not).
  5. If the deadline is consistently too short for the hardware, consider increasing it in code (the 5/30 split is hardcoded).

Example fix

// before — hardcoded 5/30 minute split
var deadline = DateTime.UtcNow.AddMinutes(hasLocalModel ? 5 : 30);

// after — configurable for slow hardware
var baseMinutes = hasLocalModel ? 5 : 30;
var extra = Se.Settings.Video.TextToSpeech.CrispAsrExtraStartupMinutes;
var deadline = DateTime.UtcNow.AddMinutes(baseMinutes + extra);
Defensive patterns

Strategy: retry

Validate before calling

// Check if models are staged to predict load time
var hasLocalModel = OmniVoiceCrispAsr.AreModelsInstalled(modelKey);
if (!hasLocalModel)
    Se.WriteToolsLog("First-run download will take up to 30 min for ~1.6 GB.");

Type guard

null

Try / catch

catch (TimeoutException ex) when (ex.Message.Contains("did not report healthy"))
{
    // Server may still be loading. Retry once, or pre-download models.
    if (attempt == 0 && hasLocalModel) { await Task.Delay(TimeSpan.FromMinutes(1), ct); goto retry; }
    throw;
}

Prevention

When it happens

Trigger: The startup while-loop exhausts the deadline without ProbeHealthAsync returning true. The server process is still running but the /health endpoint never went green — typically because model loading or first-run download took longer than the configured window.

Common situations: First-run auto-download of the ~1.6 GB F16 model on a very slow or throttled connection; the model sits on a network drive with high latency; CPU-only loading on a machine under heavy load; Hugging Face rate-limiting during --auto-download; the crispasr build's /health endpoint has a different path or semantics than expected by ProbeHealthAsync.

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/f2a2080e33851653. Report an issue: GitHub.