docling-project/docling · error · RuntimeError
Archive member '{image_info.path}' is not a regular file (di
Error message
Archive member '{image_info.path}' is not a regular file (directory or symlink in tar). What it means
RuntimeError raised while extracting a page image from a METS/GBS archive: tarfile.extractfile() returned None for the member referenced by the page's 'image' fileGrp entry. extractfile() returns None for non-regular members (directories, symlinks, devices), so the METS metadata points at something that is not a readable file — an integrity/security check against path traversal via tar links.
Source
Thrown at docling/backend/mets_gbs_backend.py:388
# A page's fileGrp entries in the METS XML are independently optional (see
# _PageFiles), so a page can legitimately have no `image` or `coordOCR` fptr
# (e.g. a blank/cover page with no OCR layer). Report it as unparseable rather
# than asserting, so the caller can mark it invalid and skip it, consistent
# with how sibling PDF backends (e.g. DoclingParsePageBackend) handle a page
# they can't build.
image_info = self.page_map[page_no].image
ocr_info = self.page_map[page_no].coordOCR
if image_info is None or ocr_info is None:
_log.warning(
f"Page {page_no} is missing an 'image' or 'coordOCR' fileGrp entry; "
"skipping."
)
return None, None
# Security: limit extraction size to prevent decompression bombs
image_file = self._tar.extractfile(image_info.path)
if image_file is None:
raise RuntimeError(
f"Archive member '{image_info.path}' is not a regular file "
"(directory or symlink in tar)."
)
image_file = cast(tarfile.ExFileObject, image_file)
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)View on GitHub (pinned to 61d76f1ff3)
Solutions
- Repack the archive materializing symlinks into real files: `tar -czhf` behaviors aside, use `tar -xzf` then `tar -czf` from the extracted tree.
- Verify each page's image entry with tarfile.getmember(path).isreg() before conversion.
- Regenerate the METS package from the source system so fileGrp references match actual members.
- Reject untrusted archives that fail this check — symlink members in a METS package are not legitimate.
Example fix
# before
result = converter.convert(mets_path) # RuntimeError: not a regular file
# after (pre-check members are regular files)
import tarfile
with tarfile.open(mets_path) as t:
bad = [m.name for m in t.getmembers() if not m.isfile() and not m.isdir()]
assert not bad, f'archive contains non-regular members: {bad}'
result = converter.convert(mets_path) Defensive patterns
Strategy: validation
Validate before calling
import tarfile
def image_members_are_regular(tar_path: str) -> bool:
with tarfile.open(tar_path) as t:
return all(m.isfile() for m in t.getmembers() if m.name.endswith(('.png', '.jpg', '.jpeg'))) Try / catch
try:
result = converter.convert(mets_path)
except RuntimeError as e:
if 'not a regular file' in str(e) and 'image' in str(e):
log.error('METS image entry is a link/dir in %s — repack required', mets_path) Prevention
- Repack archives from extracted trees to eliminate symlinked image members.
- Validate isreg() on image members during ingest.
- Treat link members in METS packages as tampering on untrusted input.
When it happens
Trigger: Converting a METS archive where the fileGrp image entry resolves to a directory, a symlink, or a hard link instead of a regular file member; also when the referenced member name is absent from the archive in a form extractfile can open.
Common situations: Hand-assembled or repacked archives that converted regular files to symlinks (e.g. `tar -cf` with symlinked trees), METS files referencing entries by slightly different paths, or tampered archives attempting link-based tricks.
Related errors
- Archive member '{ocr_info.path}' is not a regular file (dire
- Archive exceeds maximum member count limit of {self.options.
- XML file {member.name} exceeds size limit of {self.options.m
- Archive exceeds maximum total extraction size of {self.optio
- Image file {image_info.path} exceeds individual file size li
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/ecbbde57e94c4883.
Report an issue: GitHub.