SubtitleEdit/subtitleedit · error · InvalidOperationException
Failed to start crispasr (indextts)
Error message
Failed to start crispasr (indextts)
What it means
InvalidOperationException from IndexTtsCrispAsr.EnsureServerRunningAsync when `Process.Start(psi)` returns null. On modern .NET Process.Start for a real process effectively never returns null (it throws on failure), so this throw is a defensive guard for a theoretical null return — in practice you will more often see a Win32Exception first. If reached, it means the OS refused to spawn the configured exe/args combination without a thrown exception.
Source
Thrown at src/ui/Features/Video/TextToSpeech/Engines/IndexTtsCrispAsr.cs:575
{
psi.ArgumentList.Add("--auto-download");
}
psi.ArgumentList.Add("--host");
psi.ArgumentList.Add("127.0.0.1");
psi.ArgumentList.Add("--port");
psi.ArgumentList.Add(port.ToString());
// /v1/audio/speech gates `voice` field on --voice-dir being set. Same as Qwen3.
psi.ArgumentList.Add("--voice-dir");
psi.ArgumentList.Add(GetSetVoicesFolder());
// Required for indextts: the server-mode voice cloning only respects the startup
// --voice path. Skipping this means the request's `voice` is ignored and the synth
// produces noise. See CrispASR 0.6.11 upstream bug.
psi.ArgumentList.Add("--voice");
psi.ArgumentList.Add(voicePath);
CrispAsrTtsProvenance.AddServerMarkingArgs(psi.ArgumentList, exe);
var process = Process.Start(psi)
?? throw new InvalidOperationException("Failed to start crispasr (indextts)");
var launchCommand = FormatLaunchCommand(exe, psi.ArgumentList);
_serverLaunchCommand = launchCommand;
Se.WriteToolsLog("IndexTTS (CrispASR) server starting — "
+ $"PID: {process.Id}, "
+ $"Cmd: {launchCommand}");
lock (_serverLog) _serverLog.Clear();
process.ErrorDataReceived += (_, e) =>
{
if (e.Data != null) lock (_serverLog) _serverLog.AppendLine(e.Data);
};
process.OutputDataReceived += (_, e) =>
{
if (e.Data != null) lock (_serverLog) _serverLog.AppendLine(e.Data);
};
process.BeginErrorReadLine();
process.BeginOutputReadLine();View on GitHub (pinned to 17a9f07487)
Solutions
- Treat this as 'spawn failed for an unknown reason' and check exe path, permissions, and PATH.
- Confirm GetCrispAsrExecutable() exists and is executable.
- Run the exact launch command (logged just after) by hand to see the real OS error.
- Update the .NET runtime if you genuinely hit a null return, then file a bug.
Defensive patterns
Strategy: try-catch
Validate before calling
// Defensive: verify exe before spawn (real failures throw Win32Exception, not null)
if (!File.Exists(exe)) { throw new FileNotFoundException("exe missing", exe); } Try / catch
try { await indexEngine.Speak(...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Failed to start crispasr"))
{
// Rare; fall back to manual reproduction of the logged launch command.
ShowLaunchCommand(ex.Message);
} Prevention
- Pre-validate exe existence and executability before calling Speak.
- Log the full launch command (the code already does) to reproduce manually.
- Keep the .NET runtime current; a real null return is an upstream bug.
- On spawn failures, check PATH/permissions before retrying.
When it happens
Trigger: Essentially unreachable on current .NET; historically could surface if the runtime shim returned null for a missing executable. The real failure modes (missing exe, bad path) throw FileNotFoundException/Win32Exception before this line.
Common situations: Observed only on runtimes/shims that return null instead of throwing; otherwise a dead branch.
Related errors
- Failed to start crispasr (cosyvoice3-tts)
- Failed to start crispasr (f5-tts)
- Voice is not an IndexTtsVoice
- IndexTTS (CrispASR) requires a reference voice WAV. Import o
- IndexTTS (CrispASR) — the crispasr server crashed during syn
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/df6020a34604dc48.
Report an issue: GitHub.