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

  1. Read the stderr in the error message — it pinpoints the Python-level cause.
  2. Pre-download the language model by running `paddleocr ocr -l <lang>` once interactively.
  3. Align paddleocr and paddlepaddle versions (`pip install -U paddleocr paddlepaddle`).
  4. For GPU/CPU issues, install `paddlepaddle` (CPU) instead of `paddlepaddle-gpu`.
  5. 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

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


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/84a06e379f79c45c. Report an issue: GitHub.