ocrmypdf/OCRmyPDF · info · NotImplementedError

This OcrEngine does not implement generate_ocr()

Error message

This OcrEngine does not implement generate_ocr()

What it means

OcrEngine.generate_ocr() is optional; the base class raises NotImplementedError by design. The pipeline is expected to call generate_hocr() or generate_pdf() instead when an engine does not implement the direct OCR text path.

Source

Thrown at src/ocrmypdf/pluginspec.py:544

        This function executes in a worker thread or worker process. OCRmyPDF
        automatically parallelizes OCR over pages. The OCR engine should not
        introduce more parallelism.

        Args:
            input_file: A page image on which to perform OCR.
            options: The command line options.
            page_number: Zero-indexed page number (for multi-page context).

        Returns:
            A tuple of (OcrElement tree for the page, plain text content).
            The OcrElement should have ocr_class=OcrClass.PAGE as its root.

        Note:
            This method is optional. Engines that don't implement it should
            leave the default implementation, and the pipeline will fall back to
            generate_hocr() or generate_pdf().
        """
        raise NotImplementedError("This OcrEngine does not implement generate_ocr()")


@hookspec(firstresult=True)
def get_ocr_engine(options: OcrOptions | None) -> OcrEngine:  # type: ignore[return-value]
    """Returns an OcrEngine to use for processing this file.

    The OcrEngine may be instantiated multiple times, by both the main process
    and child process.

    When multiple OCR engine plugins are installed, plugins should check
    ``options.ocr_engine`` and return ``None`` if they are not the selected
    engine. The hook caller will then try the next plugin.

    Args:
        options: The current OcrOptions, used to determine which engine
            to select. May be None for backward compatibility with external
            plugins.

View on GitHub (pinned to 5074a0b0e1)

Solutions

  1. Implement generate_ocr() in your OcrEngine subclass if you want the direct path
  2. Otherwise call/let the pipeline fall back to generate_hocr() or generate_pdf()
  3. Guard with hasattr or try NotImplementedError before calling directly

Example fix

// before
text = engine.generate_ocr(image, options)
// after
text = engine.generate_ocr(image, options) if hasattr(type(engine), 'generate_ocr') and OcrEngine.generate_ocr is not type(engine).generate_ocr else engine.generate_hocr(image, options)
Defensive patterns

Strategy: type-guard

Type guard

def supports_generate_ocr(engine: OcrEngine) -> bool:\n    return type(engine).generate_ocr is not OcrEngine.generate_ocr

Try / catch

try:\n    result = engine.generate_ocr(image, options)\nexcept NotImplementedError:\n    result = engine.generate_hocr(image, options)

Prevention

When it happens

Trigger: Calling engine.generate_ocr() on an engine subclass that only implements generate_hocr() or generate_pdf(), or a plugin engine that hasn't overridden the optional method.

Common situations: Custom OCR engine plugin authors testing their engine directly; code that assumes all engines support the direct-text API.

Related errors


AI-assisted analysis of ocrmypdf/OCRmyPDF@5074a0b0e1 (2026-08-27). Data as JSON: /api/errors/39822a7ce623e26c. Report an issue: GitHub.