docling-project/docling · error · RuntimeError

Page image dimensions {im.size} do not match page geometry (

Error message

Page image dimensions {im.size} do not match page geometry ({page_size.width}x{page_size.height}).

What it means

RuntimeError from MetsGbsDocumentBackend.get_page_image(): the backend loads a page image from the METS/GBS tar archive and compares its pixel size against the page geometry declared in the METS OCR XML (page div attributes). If the image file's width/height do not equal the declared page size, the archive is internally inconsistent and coordinate transforms would be wrong, so it refuses to continue.

Source

Thrown at docling/backend/mets_gbs_backend.py:156

        images = dpage.bitmap_resources

        for img in images:
            cropbox = img.rect.to_bounding_box().to_top_left_origin(
                self.get_size().height
            )

            if cropbox.area() > AREA_THRESHOLD:
                cropbox = cropbox.scaled(scale=scale)

                yield cropbox

    def get_page_image(
        self, scale: float = 1, cropbox: BoundingBox | None = None
    ) -> Image.Image:
        im = self._require_image()
        page_size = self.get_size()
        if page_size.width != im.size[0] or page_size.height != im.size[1]:
            raise RuntimeError(
                f"Page image dimensions {im.size} do not match page geometry "
                f"({page_size.width}x{page_size.height})."
            )

        if not cropbox:
            cropbox = BoundingBox(
                l=0,
                r=page_size.width,
                t=0,
                b=page_size.height,
                coord_origin=CoordOrigin.TOPLEFT,
            )

        image = im.resize(
            size=(round(page_size.width * scale), round(page_size.height * scale))
        ).crop(cropbox.scaled(scale=scale).as_tuple())
        return image

View on GitHub (pinned to 61d76f1ff3)

Solutions

  1. Verify the archive is a well-formed METS/GBS export where image dimensions match the OCR page geometry (extract and compare with PIL before conversion).
  2. Re-generate or obtain a consistent archive from the source digitization system.
  3. If you must repair: rewrite the ocr_page div attributes to the true image size, or resample images to the declared size, then reconvert.
  4. Report upstream if a stock Google Books export triggers it — stock exports should always be consistent.

Example fix

# before
result = converter.convert(mets_tar_path)  # RuntimeError: dims mismatch

# after (pre-validate the archive)
import tarfile, io
from PIL import Image
with tarfile.open(mets_tar_path) as t:
    for m in t.getmembers():
        if m.name.endswith(('.png', '.jpg')):
            im = Image.open(t.extractfile(m))
            assert im.size == declared_size.get(m.name), m.name  # repair before converting
result = converter.convert(mets_tar_path)
Defensive patterns

Strategy: validation

Validate before calling

import tarfile, io, re
from PIL import Image

def mets_image_dims_match(tar_path: str) -> bool:
    with tarfile.open(tar_path) as t:
        ocr = next((m for m in t.getmembers() if m.name.endswith('.html') or 'coordOCR' in m.name), None)
        img = next((m for m in t.getmembers() if m.name.endswith(('.png', '.jpg', '.jpeg'))), None)
        if not (ocr and img):
            return True  # cannot pre-check; let backend decide
        m = re.search(rb"bbox\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)", t.extractfile(ocr).read(4096))
        if not m:
            return True
        w, h = int(m.group(3)) - int(m.group(1)), int(m.group(4)) - int(m.group(2))
        return Image.open(t.extractfile(img)).size == (w, h)

Try / catch

try:
    result = converter.convert(mets_path)
except RuntimeError as e:
    if 'do not match page geometry' in str(e):
        log.error('inconsistent METS archive %s — image/OCR mismatch', mets_path)
        quarantine(mets_path)

Prevention

When it happens

Trigger: Converting a METS/GBS (.tar.gz with Google Books scan structure) archive where the ocr_page div's width/height attributes disagree with the actual embedded PNG/JPEG dimensions — e.g. mismatched image/OCR pairs, rescaled images, or a corrupted/hand-edited archive.

Common situations: Digitization pipelines that regenerate page images at a different resolution without updating OCR metadata, archives assembled from mixed sources, or truncated image members that PIL still opens with a partial header.

Related errors


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