SubtitleEdit/subtitleedit · error · InvalidOperationException
Failed to start crispasr (chatterbox)
Error message
Failed to start crispasr (chatterbox)
What it means
Process.Start(psi) returned null, which on modern .NET essentially never happens for a real executable — it indicates the runtime/platform could not spawn a process at all. The engine throws InvalidOperationException naming the failure.
Source
Thrown at src/ui/Features/Video/TextToSpeech/Engines/ChatterboxTtsCpp.cs:593
// and synth returns empty audio.
psi.ArgumentList.Add("--codec-model");
psi.ArgumentList.Add(GetS3GenModelPath(modelKey));
psi.ArgumentList.Add("--host");
psi.ArgumentList.Add("127.0.0.1");
psi.ArgumentList.Add("--port");
psi.ArgumentList.Add(port.ToString());
// The crispasr server gates /v1/audio/speech requests with a `voice` field
// behind --voice-dir being set ("warning: --voice-dir not set; … will reject
// requests with a 'voice' field"). Pointing --voice-dir at our voices folder
// satisfies the gate and also makes /v1/voices reflect the imported WAVs. It
// does not make the chatterbox backend look the voice up in there though -
// that is what the working directory above is for.
psi.ArgumentList.Add("--voice-dir");
psi.ArgumentList.Add(GetSetVoicesFolder());
CrispAsrTtsProvenance.AddServerMarkingArgs(psi.ArgumentList, exe);
var process = Process.Start(psi)
?? throw new InvalidOperationException("Failed to start crispasr (chatterbox)");
// Record the exact launch command in the tools log so failures later in this
// session can be reproduced from a shell. Also cache it on the static so the
// runtime/startup error paths can surface it inline with the error dialog.
var launchCommand = FormatLaunchCommand(exe, psi.ArgumentList);
_serverLaunchCommand = launchCommand;
Se.WriteToolsLog("Chatterbox TTS 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);View on GitHub (pinned to 17a9f07487)
Solutions
- Run outside any sandbox that blocks process spawning.
- Verify the exe path exists and (on POSIX) has the execute bit set.
- Check the runtime supports Process.Start on this platform.
- Capture and log psi.FileName / Arguments to reproduce manually.
Defensive patterns
Strategy: try-catch
Validate before calling
if (!File.Exists(exe)) return Invalid("exe missing: " + exe);
// nothing else to validate; Process.Start returning null is a host limitation Try / catch
try { EnsureServerRunningAsync(modelKey, ct).Wait(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Failed to start crispasr"))
{ /* host cannot spawn processes; run outside the sandbox */ } Prevention
- Run the host in an environment that permits process spawning.
- Verify execute permission on the binary on POSIX.
- Log psi.FileName + Arguments so the spawn can be reproduced manually.
When it happens
Trigger: Process.Start returns null rather than throwing — historically only on platforms/runtimes without a process-launch capability or in heavily sandboxed hosts.
Common situations: Running under a sandbox/container that blocks process creation; very old or non-standard runtime; execute permission missing on the binary on POSIX.
Related errors
- Chatterbox TTS hit a CrispASR runtime bug during synthesis (
- Chatterbox TTS request failed — the crispasr server crashed
- Chatterbox TTS request failed — the connection to the crispa
- Chatterbox TTS could not use the reference voice "{Path.GetF
- Chatterbox TTS synthesis failed ({(int)response.StatusCode})
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/992f38c48a420d73.
Report an issue: GitHub.