SubtitleEdit/subtitleedit · error · InvalidOperationException
paddleocr exited with code {proc.ExitCode}: {err}
Error message
paddleocr exited with code {proc.ExitCode}: {err} What it means
Thrown by PaddleOcrEngine.Recognize when the paddleocr subprocess exits with a non-zero code. The message embeds the exit code and the full stderr captured concurrently, so the upstream Python traceback is visible. This is a paddleocr runtime failure, not a seconv failure.
Source
Thrown at src/seconv/Core/PaddleOcrEngine.cs:102
// 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 */ }
}
}
/// <summary>
/// Parses paddleocr's stdout. The CLI prints one or more <c>[bbox], (text, conf)</c>
/// records; we extract just the recognised text from each, joining with newlines in
/// vertical order.
/// </summary>
internal static string ParseStdout(string stdout)
{
// Match: ('text', 0.95) -- the recognised text is before the comma in single quotes.
var sb = new StringBuilder();View on GitHub (pinned to 17a9f07487)
Solutions
- Read the stderr in the error message — it pinpoints the Python-level cause.
- Pre-download the language model by running `paddleocr ocr -l <lang>` once interactively.
- Align paddleocr and paddlepaddle versions (`pip install -U paddleocr paddlepaddle`).
- For GPU/CPU issues, install `paddlepaddle` (CPU) instead of `paddlepaddle-gpu`.
- Confirm the input subtitle actually produced a non-empty bitmap (the engine skips null bitmaps earlier).
Example fix
# before: paddleocr crashes with model download error seconv in.sup out.srt --ocr-engine paddle # after: pre-warm the model paddleocr ocr -l en -i dummy.png seconv in.sup out.srt --ocr-engine paddle
Defensive patterns
Strategy: try-catch
Validate before calling
// No purely-local precheck; pre-warm the model instead:
// var psi = new ProcessStartInfo("paddleocr"){ ArgumentList={"ocr","-l",lang,"-i",warmupPng}};
// run it once and ensure ExitCode==0 before the batch. Try / catch
try { text = engine.Recognize(bitmap); }
catch (InvalidOperationException ex) when (ex.Message.Contains("paddleocr exited with code"))
{
// log ex (contains stderr), skip this subtitle, continue batch
} Prevention
- Pre-warm paddleocr with one dummy image so models download before the batch.
- Pin compatible paddleocr + paddlepaddle versions in requirements.
- Log the embedded stderr verbatim for post-mortem.
When it happens
Trigger: Calling PaddleOcrEngine.Recognize (via `--ocr-engine paddle`) where paddleocr starts but errors: missing model download, CUDA/CPU mismatch, incompatible PaddlePaddle version, corrupt input image, language model not downloaded.
Common situations: First run where PaddleOCR needs to download a language model and the network/proxy blocks it; PaddlePaddle GPU build on a CPU-only machine; image passed as an unsupported format; paddleocr and paddlepaddle version skew.
Related errors
- PaddleOCR not found on PATH. Install it (e.g. `pip install p
- Failed to start paddleocr process.
- Ollama returned {(int)resp.StatusCode}: {json}
- {engine.Error}
- CrispASR exited with code {process.ExitCode}: {Error}
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/84a06e379f79c45c.
Report an issue: GitHub.