{"record":{"id":"832cba5279e09319","repo":"SubtitleEdit/subtitleedit","slug":"failed-to-start-paddleocr-process","errorCode":null,"errorMessage":"Failed to start paddleocr process.","messagePattern":"Failed to start paddleocr process\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/seconv/Core/PaddleOcrEngine.cs","lineNumber":93,"sourceCode":"                ArgumentList = { \"ocr\", \"-i\", pngPath, \"--lang\", Language, \"--use_angle_cls\", \"false\" },\n                RedirectStandardOutput = true,\n                RedirectStandardError = true,\n                StandardOutputEncoding = System.Text.Encoding.UTF8,\n                StandardErrorEncoding = System.Text.Encoding.UTF8,\n                UseShellExecute = false,\n                CreateNoWindow = true,\n            };\n\n            // StandardOutputEncoding only fixes the decoding side. paddleocr is a Python CLI, and\n            // on Windows Python encodes a *redirected* stdout with the ANSI codepage (until UTF-8\n            // becomes the default in Python 3.15, PEP 686) - so the producer side must be forced\n            // to UTF-8 too, or non-ASCII text still arrives as mojibake. Same env vars the UI's\n            // Paddle engine sets.\n            psi.EnvironmentVariables[\"PYTHONIOENCODING\"] = \"utf-8\";\n            psi.EnvironmentVariables[\"PYTHONUTF8\"] = \"1\";\n\n            using var proc = Process.Start(psi)\n                ?? throw new InvalidOperationException(\"Failed to start paddleocr process.\");\n            // Drain stderr concurrently — paddleocr is chatty on stderr, and reading stdout\n            // to completion while stderr fills the pipe buffer would deadlock.\n            var stderrTask = proc.StandardError.ReadToEndAsync();\n            var stdout = proc.StandardOutput.ReadToEnd();\n            proc.WaitForExit();\n            if (proc.ExitCode != 0)\n            {\n                var err = stderrTask.GetAwaiter().GetResult();\n                throw new InvalidOperationException($\"paddleocr exited with code {proc.ExitCode}: {err}\");\n            }\n            return ParseStdout(stdout);\n        }\n        finally\n        {\n            try { File.Delete(pngPath); } catch { /* best-effort */ }\n        }\n    }\n","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/seconv/Core/PaddleOcrEngine.cs#L75-L111","documentation":"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.","triggerScenarios":"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).","commonSituations":"The paddleocr file exists on PATH but lacks the executable bit (chmod -x); a stub/placeholder file shadowing the real binary; filesystem permission issue.","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."],"exampleFix":"# before\nls -l $(which paddleocr)   # -rw-r--r-- (no x bit)\n# after\nchmod +x $(which paddleocr)\nseconv in.sup out.srt --ocr-engine paddle","handlingStrategy":"validation","validationCode":"var paddlePath = PaddleOcrEngine.Detect();\nif (paddlePath is null) throw new InvalidOperationException(\"paddleocr missing\");\nif (OperatingSystem.IsLinux() && !HasExecuteBit(paddlePath))\n    throw new InvalidOperationException(\"paddleocr not executable: chmod +x \" + paddlePath);\n\nstatic bool HasExecuteBit(string p) => (new System.IO.FileInfo(p).UnixMode & System.IO.UnixFileMode.UserExecute) != 0;","typeGuard":"static bool IsExecutableOnPath(string name) =>\n    PaddleOcrEngine.Detect() is { } p && OperatingSystem.IsWindows() ? true : HasExecuteBit(p);","tryCatchPattern":"try { var engine = PaddleOcrEngine.Create(lang); }\ncatch (InvalidOperationException ex) when (ex.Message == \"Failed to start paddleocr process.\")\n{\n    // chmod +x, reinstall paddleocr, or fall back\n}","preventionTips":["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."],"tags":["ocr","paddleocr","process","permissions","executable"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}