SubtitleEdit/subtitleedit · error · InvalidOperationException
Failed to start omnivoice-tts
Error message
Failed to start omnivoice-tts
What it means
InvalidOperationException thrown if Process.Start(psi) returns null when launching the omnivoice-tts CLI for a single synthesis. As with errors 243 and 250, this null path is practically unreachable with UseShellExecute=false; the realistic failure is a Win32Exception when the binary cannot execute.
Source
Thrown at src/ui/Features/Video/TextToSpeech/Engines/OmniVoiceTtsCpp.cs:323
psi.ArgumentList.Add(refTextPath);
}
// Voice-design keywords (--instruct) only shape the voice when there is no reference
// audio - with --ref-wav omnivoice-tts takes the voice from the clone and ignores them.
if (!usingReference)
{
var instruction = (Se.Settings.Video.TextToSpeech.OmniVoiceTtsCppInstruction ?? string.Empty).Trim();
if (!string.IsNullOrEmpty(instruction))
{
psi.ArgumentList.Add("--instruct");
psi.ArgumentList.Add(instruction);
}
}
Se.WriteToolsLog($"OmniVoice TTS: {exe} {string.Join(' ', psi.ArgumentList)} (voice={omniVoice}, textLen={text.Length})");
var process = Process.Start(psi)
?? throw new InvalidOperationException("Failed to start omnivoice-tts");
try
{
var stderrTask = process.StandardError.ReadToEndAsync(cancellationToken);
var stdoutTask = process.StandardOutput.ReadToEndAsync(cancellationToken);
await process.StandardInput.WriteAsync(inputText.AsMemory(), cancellationToken);
process.StandardInput.Close();
await process.WaitForExitAsync(cancellationToken);
var stderr = await stderrTask;
var stdout = await stdoutTask;
if (process.ExitCode != 0 || !File.Exists(outputFileName))
{
// A process killed by the Windows loader (e.g. missing CUDA runtime, issue #13196)
// never reaches main, so stderr is empty and the bare exit code is all the user sees.
// NativeExitCodeHelper turns the known status codes into an actionable sentence.View on GitHub (pinned to 17a9f07487)
Solutions
- Verify ProcessStartInfo.UseShellExecute is false.
- If the binary genuinely won't start, the real error is a Win32Exception — wrap Process.Start in try/catch(Win32Exception) for a useful message.
- Confirm the executable is not blocked (Windows Mark-of-the-Web) or quarantined.
- Check execute permissions on Linux/macOS (chmod +x).
Example fix
// before
var process = Process.Start(psi)
?? throw new InvalidOperationException("Failed to start omnivoice-tts");
// after — catch the real failure mode
try { var process = Process.Start(psi); }
catch (Win32Exception ex) when (ex.NativeErrorCode == 5)
{
throw new InvalidOperationException("omnivoice-tts is not executable. Run chmod +x.", ex);
}
catch (Win32Exception ex)
{
throw new InvalidOperationException($"Failed to start omnivoice-tts: {ex.Message}", ex);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Verify binary exists and is executable
var exe = GetExecutableFileName();
if (!File.Exists(exe)) throw new FileNotFoundException("Missing: " + exe, exe); Type guard
null
Try / catch
catch (InvalidOperationException ex) when (ex.Message == "Failed to start omnivoice-tts")
{
Se.LogError(ex, "Process.Start returned null unexpectedly.");
throw;
} Prevention
- This path is dead code with UseShellExecute=false; handle Win32Exception instead.
- Verify execute permissions (chmod +x) on Linux/macOS.
- Check for Windows Mark-of-the-Web blocking on downloaded binaries.
When it happens
Trigger: Process.Start(psi) returns null. With UseShellExecute=false, Process.Start throws rather than returning null. This guard is defensive dead code under the current configuration.
Common situations: Unreachable in production. If observed, check whether UseShellExecute was changed, or whether a framework-level issue caused a null return.
Related errors
- Failed to start crispasr (omnivoice)
- Failed to start crispasr (moss-tts)
- crispasr (omnivoice) exited during startup (code {exitCode})
- {detail} {stderr}
- crispasr (moss-tts) exited during startup (code {exitCode}).
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/807167ddab01ac9b.
Report an issue: GitHub.