{"record":{"id":"fe7d4f98b8e758c3","repo":"ocrmypdf/OCRmyPDF","slug":"nullocrengine-cannot-generate-pdfs-directly-use","errorCode":null,"errorMessage":"NullOcrEngine cannot generate PDFs directly. Use --pdf-renderer fpdf2 instead of sandwich mode.","messagePattern":"NullOcrEngine cannot generate PDFs directly\\. Use --pdf-renderer fpdf2 instead of sandwich mode\\.","errorType":"validation","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"src/ocrmypdf/builtin_plugins/null_ocr.py","lineNumber":146,"sourceCode":"    </div>\n</body>\n</html>\n'''\n        output_hocr.write_text(hocr_content, encoding='utf-8')\n        output_text.write_text('', encoding='utf-8')\n\n    @staticmethod\n    def generate_pdf(\n        input_file: Path,\n        output_pdf: Path,\n        output_text: Path,\n        options: OcrOptions,\n    ) -> None:\n        \"\"\"NullOcrEngine cannot generate PDFs directly.\n\n        Use pdf_renderer='fpdf2' instead of 'sandwich'.\n        \"\"\"\n        raise NotImplementedError(\n            \"NullOcrEngine cannot generate PDFs directly. \"\n            \"Use --pdf-renderer fpdf2 instead of sandwich mode.\"\n        )\n\n\n@hookimpl\ndef get_ocr_engine(options):\n    \"\"\"Return NullOcrEngine when --ocr-engine none is selected.\"\"\"\n    if options is not None:\n        ocr_engine = getattr(options, 'ocr_engine', 'auto')\n        if ocr_engine != 'none':\n            return None\n    return NullOcrEngine()\n","sourceCodeStart":128,"sourceCodeEnd":160,"githubUrl":"https://github.com/ocrmypdf/OCRmyPDF/blob/5074a0b0e109362422b768fd271ed84bf717c4ec/src/ocrmypdf/builtin_plugins/null_ocr.py#L128-L160","documentation":"NullOcrEngine is a no-op OCR engine; it can report 'no text found' but its generate_pdf() unconditionally raises NotImplementedError because it cannot render an invisible-text sandwich PDF itself. Sandwich rendering with this engine is a programming/configuration error.","triggerScenarios":"Selecting the null engine (e.g. via --force-ocr alternatives or a plugin routing to NullOcrEngine) while the pdf_renderer is 'sandwich' (hocr).","commonSituations":"Using the null engine to strip/normalize PDFs while forgetting to set --pdf-renderer fpdf2.","solutions":["Set pdf_renderer='fpdf2' (options.pdf_renderer) so no sandwich page generation is needed.","If you intentionally want no OCR text, verify no plugin resolves to NullOcrEngine for sandwich mode."],"exampleFix":"# before\nocr(in, out, pdf_renderer='sandwich', ...)  # engine = NullOcrEngine\n# after\nocr(in, out, pdf_renderer='fpdf2', ...)","handlingStrategy":"validation","validationCode":"assert not (engine_is_null and options.pdf_renderer == 'sandwich'), \\\n    'NullOcrEngine requires pdf_renderer=fpdf2'","typeGuard":null,"tryCatchPattern":"try:\n    ocr(in, out, pdf_renderer='sandwich')\nexcept NotImplementedError as e:\n    if 'NullOcrEngine' in str(e):\n        ocr(in, out, pdf_renderer='fpdf2')\n    raise","preventionTips":["Whenever the null engine is selected, always set pdf_renderer='fpdf2'.","Validate engine/renderer compatibility in a preflight check for custom plugin sets."],"tags":["ocrmypdf","null-engine","pdf-renderer","not-implemented"],"backgroundTag":"unsupported-operation-misconfiguration","analyzedSha":"5074a0b0e109362422b768fd271ed84bf717c4ec","analyzedAt":"2026-08-27T11:57:38.523Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}