docling-project/docling · error · RuntimeError

Archive member '{ocr_info.path}' is not a regular file (dire

Error message

Archive member '{ocr_info.path}' is not a regular file (directory or symlink in tar).

What it means

RuntimeError raised when tarfile.extractfile() returns None for the member named by the page's 'coordOCR' fileGrp entry — meaning that member is a directory, symlink, or other non-regular file. It is the OCR-side twin of the image-member check: METS metadata must point at a real, extractable file, and link/directory members are rejected as both invalid and a potential tar-based attack.

Source

Thrown at docling/backend/mets_gbs_backend.py:411

        image_data = image_file.read(self.options.max_file_bytes + 1)
        if len(image_data) > self.options.max_file_bytes:
            raise ValueError(
                f"Image file {image_info.path} exceeds individual file size limit of {self.options.max_file_bytes} bytes"
            )

        # Security: Track total bytes extracted
        self._total_bytes_extracted += len(image_data)
        if self._total_bytes_extracted > self.options.max_total_bytes:
            raise ValueError(
                f"Total extracted data exceeds maximum limit of {self.options.max_total_bytes} bytes"
            )

        buf = BytesIO(image_data)
        im: PILImage = Image.open(buf)

        ocr_file = self._tar.extractfile(ocr_info.path)
        if ocr_file is None:
            raise RuntimeError(
                f"Archive member '{ocr_info.path}' is not a regular file "
                "(directory or symlink in tar)."
            )
        ocr_file = cast(tarfile.ExFileObject, ocr_file)
        ocr_content = ocr_file.read(self.options.max_file_bytes + 1)
        if len(ocr_content) > self.options.max_file_bytes:
            raise ValueError(
                f"OCR file {ocr_info.path} exceeds individual file size limit of {self.options.max_file_bytes} bytes"
            )

        # Security: Track total bytes extracted
        self._total_bytes_extracted += len(ocr_content)
        if self._total_bytes_extracted > self.options.max_total_bytes:
            raise ValueError(
                f"Total extracted data exceeds maximum limit of {self.options.max_total_bytes} bytes"
            )

        parser = etree.HTMLParser(no_network=True)

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Repack from an extracted tree so all members are regular files.
  2. Verify OCR member names in the tar match the FLocat hrefs in the METS file exactly (case included).
  3. Regenerate the METS package from the source digitization tool.
  4. Treat failures on untrusted archives as malicious input and quarantine the file.

Example fix

# before
result = converter.convert(mets_path)  # RuntimeError: coordOCR not regular

# after
import tarfile
with tarfile.open(mets_path) as t:
    names = {m.name: m for m in t.getmembers()}
    for href in mets_ocr_hrefs:  # FLocat xlink:href values
        assert href in names and names[href].isfile(), href
result = converter.convert(mets_path)
Defensive patterns

Strategy: validation

Validate before calling

import tarfile

def ocr_members_are_regular(tar_path: str) -> bool:
    with tarfile.open(tar_path) as t:
        ocr = [m for m in t.getmembers() if 'ocr' in m.name.lower() or m.name.endswith(('.html', '.htm'))]
        return all(m.isfile() for m in ocr) if ocr else True

Try / catch

try:
    result = converter.convert(mets_path)
except RuntimeError as e:
    if 'not a regular file' in str(e):
        log.error('coordOCR member is a link/dir in %s — repack from extracted tree', mets_path)

Prevention

When it happens

Trigger: Converting a METS GBS archive whose coordOCR entries reference symlinks/directories, or whose OCR member names do not exactly match the tar member names so extractfile resolves to nothing openable.

Common situations: Repacked archives that turned files into symlinks, case-sensitivity mismatches (Ocr.XML vs ocr.xml) introduced by repacking on case-insensitive filesystems, or edited METS files with wrong fileGrp paths.

Related errors


AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14). Data as JSON: /api/errors/33aece80e52c4b1c. Report an issue: GitHub.