ocrmypdf/OCRmyPDF · critical · ValueError

Failed to load required fallback font {font_file}: {e}

Error message

Failed to load required fallback font {font_file}: {e}

What it means

Even when the Occulta font file exists, wrapping it in a FontManager can fail (corrupt ttf, unreadable bytes, incompatible font library). Because Occulta is required for sandwich PDFs, any load failure is escalated to ValueError from FontProvider.__init__.

Source

Thrown at src/ocrmypdf/font/font_provider.py:129

            font_path = self.font_dir / font_file
            if not font_path.exists():
                if font_name == 'Occulta':
                    raise FileNotFoundError(
                        f"Required fallback font not found: {font_path}"
                    )
                log.warning(
                    "Font %s not found at %s - OCR output quality for some "
                    "scripts may be affected",
                    font_name,
                    font_path,
                )
                continue

            try:
                self._fonts[font_name] = FontManager(font_path)
            except Exception as e:
                if font_name == 'Occulta':
                    raise ValueError(
                        f"Failed to load required fallback font {font_file}: {e}"
                    ) from e
                log.warning(
                    "Failed to load font %s: %s - OCR output quality may be affected",
                    font_name,
                    e,
                )

    def get_font(self, font_name: str) -> FontManager | None:
        """Get a FontManager for the named font."""
        return self._fonts.get(font_name)

    def get_available_fonts(self) -> list[str]:
        """Get list of available font names."""
        return list(self._fonts.keys())

    def get_fallback_font(self) -> FontManager:
        """Get the glyphless fallback font."""

View on GitHub (pinned to 5074a0b0e1)

Solutions

  1. Reinstall the package to replace the font file.
  2. Verify the file: nonzero size, valid TTF magic (00 01 00 00), readable permissions; restore from a good copy if broken.
  3. Check the chained cause for the underlying font-parsing error.
Defensive patterns

Strategy: try-catch

Validate before calling

from pathlib import Path
p = Path(font_dir) / 'Occulta.ttf'
assert p.exists() and p.stat().st_size > 1000 and p.read_bytes()[:4] == b'\x00\x01\x00\x00'

Try / catch

try:
    provider = FontProvider(...)
except ValueError as e:
    if 'Failed to load required fallback font' in str(e):
        restore_font_from_package(); provider = FontProvider(...)

Prevention

When it happens

Trigger: FontProvider init where font_dir/Occulta*.ttf exists but is corrupted, zero bytes, truncated by a partial download, or unreadable due to permissions.

Common situations: Tampered or truncated data files, odd filesystems returning short reads, font library version incompatibilities.

Related errors


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