SubtitleEdit/subtitleedit · error · InvalidOperationException
Failed to start paddleocr process.
Error message
Failed to start paddleocr process.
What it means
Thrown when `Process.Start(psi)` returns null on a paddleocr invocation. Per .NET docs Process.Start returns null only when no process resource is started (e.g. the executable resolved to a document and a shell opened it) — with UseShellExecute=false this is effectively unreachable for a real binary, so hitting it usually means the resolved path points to something the OS will not launch as a process.
Source
Thrown at src/seconv/Core/PaddleOcrEngine.cs:93
ArgumentList = { "ocr", "-i", pngPath, "--lang", Language, "--use_angle_cls", "false" },
RedirectStandardOutput = true,
RedirectStandardError = true,
StandardOutputEncoding = System.Text.Encoding.UTF8,
StandardErrorEncoding = System.Text.Encoding.UTF8,
UseShellExecute = false,
CreateNoWindow = true,
};
// StandardOutputEncoding only fixes the decoding side. paddleocr is a Python CLI, and
// on Windows Python encodes a *redirected* stdout with the ANSI codepage (until UTF-8
// becomes the default in Python 3.15, PEP 686) - so the producer side must be forced
// to UTF-8 too, or non-ASCII text still arrives as mojibake. Same env vars the UI's
// Paddle engine sets.
psi.EnvironmentVariables["PYTHONIOENCODING"] = "utf-8";
psi.EnvironmentVariables["PYTHONUTF8"] = "1";
using var proc = Process.Start(psi)
?? throw new InvalidOperationException("Failed to start paddleocr process.");
// Drain stderr concurrently — paddleocr is chatty on stderr, and reading stdout
// to completion while stderr fills the pipe buffer would deadlock.
var stderrTask = proc.StandardError.ReadToEndAsync();
var stdout = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
if (proc.ExitCode != 0)
{
var err = stderrTask.GetAwaiter().GetResult();
throw new InvalidOperationException($"paddleocr exited with code {proc.ExitCode}: {err}");
}
return ParseStdout(stdout);
}
finally
{
try { File.Delete(pngPath); } catch { /* best-effort */ }
}
}
View on GitHub (pinned to 17a9f07487)
Solutions
- Ensure the paddleocr file is executable: `chmod +x $(which paddleocr)`.
- Reinstall paddleocr cleanly so the executable bit is set by pip.
- Check that the file at the detected path is the real launcher, not a text stub.
- Run `paddleocr --help` manually in the same shell to confirm it launches.
Example fix
# before ls -l $(which paddleocr) # -rw-r--r-- (no x bit) # after chmod +x $(which paddleocr) seconv in.sup out.srt --ocr-engine paddle
Defensive patterns
Strategy: validation
Validate before calling
var paddlePath = PaddleOcrEngine.Detect();
if (paddlePath is null) throw new InvalidOperationException("paddleocr missing");
if (OperatingSystem.IsLinux() && !HasExecuteBit(paddlePath))
throw new InvalidOperationException("paddleocr not executable: chmod +x " + paddlePath);
static bool HasExecuteBit(string p) => (new System.IO.FileInfo(p).UnixMode & System.IO.UnixFileMode.UserExecute) != 0; Type guard
static bool IsExecutableOnPath(string name) =>
PaddleOcrEngine.Detect() is { } p && OperatingSystem.IsWindows() ? true : HasExecuteBit(p); Try / catch
try { var engine = PaddleOcrEngine.Create(lang); }
catch (InvalidOperationException ex) when (ex.Message == "Failed to start paddleocr process.")
{
// chmod +x, reinstall paddleocr, or fall back
} Prevention
- After pip install, verify the executable bit on Unix.
- Run `paddleocr --help` in CI to confirm it launches.
- Detect() once at startup and fail with a clearer message.
When it happens
Trigger: PaddleOcrEngine.Recognize invoking Process.Start where Detect() returned a path that is not an executable (a script without a shebang on Unix, a non-executable file, or a path whose execute bit is unset).
Common situations: The paddleocr file exists on PATH but lacks the executable bit (chmod -x); a stub/placeholder file shadowing the real binary; filesystem permission issue.
Related errors
- paddleocr exited with code {proc.ExitCode}: {err}
- PaddleOCR not found on PATH. Install it (e.g. `pip install p
- {engine.Error}
- Failed to start yt-dlp
- Failed to open file: {filePath}
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/832cba5279e09319.
Report an issue: GitHub.