{"record":{"id":"dae4d1a248d317b9","repo":"docling-project/docling","slug":"ocr-file-ocr-info-path-exceeds-individual-file-s","errorCode":null,"errorMessage":"OCR file {ocr_info.path} exceeds individual file size limit of {self.options.max_file_bytes} bytes","messagePattern":"OCR file (.+?) exceeds individual file size limit of (.+?) bytes","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"docling/backend/mets_gbs_backend.py","lineNumber":418,"sourceCode":"        self._total_bytes_extracted += len(image_data)\n        if self._total_bytes_extracted > self.options.max_total_bytes:\n            raise ValueError(\n                f\"Total extracted data exceeds maximum limit of {self.options.max_total_bytes} bytes\"\n            )\n\n        buf = BytesIO(image_data)\n        im: PILImage = Image.open(buf)\n\n        ocr_file = self._tar.extractfile(ocr_info.path)\n        if ocr_file is None:\n            raise RuntimeError(\n                f\"Archive member '{ocr_info.path}' is not a regular file \"\n                \"(directory or symlink in tar).\"\n            )\n        ocr_file = cast(tarfile.ExFileObject, ocr_file)\n        ocr_content = ocr_file.read(self.options.max_file_bytes + 1)\n        if len(ocr_content) > self.options.max_file_bytes:\n            raise ValueError(\n                f\"OCR file {ocr_info.path} exceeds individual file size limit of {self.options.max_file_bytes} bytes\"\n            )\n\n        # Security: Track total bytes extracted\n        self._total_bytes_extracted += len(ocr_content)\n        if self._total_bytes_extracted > self.options.max_total_bytes:\n            raise ValueError(\n                f\"Total extracted data exceeds maximum limit of {self.options.max_total_bytes} bytes\"\n            )\n\n        parser = etree.HTMLParser(no_network=True)\n        ocr_root: etree._Element = etree.fromstring(ocr_content, parser=parser)\n\n        line_cells: list[TextCell] = []\n        word_cells: list[TextCell] = []\n\n        page_div = ocr_root.xpath(\"//div[@class='ocr_page']\")\n","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/backend/mets_gbs_backend.py#L400-L436","documentation":"ValueError raised when a page's coordOCR member (HTML-ish OCR coordinate file) exceeds options.max_file_bytes after decompression. The OCR bytes are read with a bounded read(max_file_bytes+1) and rejected if over the cap — the same per-file bomb guard as images, applied to the OCR side of each page.","triggerScenarios":"Converting a METS book where an hOCR/coordOCR file for some page is larger than max_file_bytes; trips during that page's conversion, after the image was already extracted and counted against the total.","commonSituations":"Very dense OCR files (word-level coordinates on dense scans), word-art or noisy pages generating huge hOCR, or a reduced max_file_bytes in options.","solutions":["Raise MetsGbsBackendOptions(max_file_bytes=...) to exceed your largest OCR member.","Identify the offending member with `tar -tvzf book.tar.gz | grep -i ocr | sort -k3 -n | tail`.","Regenerate OCR at word level with fewer redundant elements, or simplify the hOCR, then repackage.","Keep a limit in place for untrusted archives."],"exampleFix":"# before\nresult = converter.convert(mets_path)  # ValueError: OCR file exceeds limit\n\n# after\nopts = MetsGbsBackendOptions(max_file_bytes=128 * 1024 * 1024)\n# wire into converter format options, then convert\nresult = converter.convert(mets_path)","handlingStrategy":"validation","validationCode":"import tarfile\n\ndef ocr_within_cap(tar_path: str, cap: int) -> bool:\n    with tarfile.open(tar_path) as t:\n        ocr = [m for m in t.getmembers() if 'ocr' in m.name.lower() or m.name.endswith(('.html', '.htm'))]\n        return all(m.size <= cap for m in ocr) if ocr else True","typeGuard":null,"tryCatchPattern":"try:\n    result = converter.convert(mets_path)\nexcept ValueError as e:\n    if 'OCR file' in str(e) and 'size limit' in str(e):\n        opts = MetsGbsBackendOptions(max_file_bytes=CAP)\n        result = converter_with(opts).convert(mets_path)\n    else:\n        raise","preventionTips":["Measure OCR member sizes before conversion and set max_file_bytes above the max.","Simplify word-level hOCR for dense pages before packaging.","Record the failing page id when caught so regeneration can target it."],"tags":["mets","archive","security","limits","ocr"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}