{"record":{"id":"a11678c3b047a1c6","repo":"docling-project/docling","slug":"model-self-name-returned-wrong-number-of-pages","errorCode":null,"errorMessage":"Model {self.name} returned wrong number of pages","messagePattern":"Model (.+?) returned wrong number of pages","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"docling/pipeline/standard_pdf_pipeline.py","lineNumber":365,"sourceCode":"                    continue\n\n                pages: list[Page] = [payload for _, payload in pages_with_payloads]\n                if _log.isEnabledFor(logging.DEBUG):\n                    _t_start = time.time()\n                    _t_mono = time.monotonic()\n                processed_pages = list(self.model(good[0].conv_res, pages))  # type: ignore[arg-type]\n                if _log.isEnabledFor(logging.DEBUG):\n                    _log.debug(\n                        \"PIPELINE_PROFILING Stage %s: run_id=%d pages=%s start=%.3f end=%.3f duration=%.3fs\",\n                        self.name,\n                        rid,\n                        [it.page_no for it in good],\n                        _t_start,\n                        time.time(),\n                        time.monotonic() - _t_mono,\n                    )\n                if len(processed_pages) != len(pages):  # strict mismatch guard\n                    raise RuntimeError(\n                        f\"Model {self.name} returned wrong number of pages\"\n                    )\n                for idx, page in enumerate(processed_pages):\n                    result.append(\n                        ThreadedItem(\n                            payload=page,\n                            run_id=rid,\n                            page_no=good[idx].page_no,\n                            conv_res=good[idx].conv_res,\n                        )\n                    )\n            except Exception as exc:\n                _log.error(\n                    \"Stage %s failed for run %d: %s\", self.name, rid, exc, exc_info=True\n                )\n                for it in good:\n                    it.is_failed = True\n                    it.error = exc","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/pipeline/standard_pdf_pipeline.py#L347-L383","documentation":"In the threaded execution path of StandardPdfPipeline, each pipeline stage model is invoked with a batch of pages and must return exactly one result per input page. After the model call, a strict mismatch guard compares len(processed_pages) with len(pages) and raises this RuntimeError if the model dropped, merged, or added pages. It signals a broken stage model implementation (typically a custom or experimental model), not a user input problem.","triggerScenarios":"Plugging a custom model into a StandardPdfPipeline stage whose __call__ returns a list with a different length than the pages it received; a stage that filters out pages (e.g. skips pages it cannot parse) inside the threaded worker; monkey-patched or subclassed models that aggregate page results.","commonSituations":"Extending docling with a custom layout or OCR model that returns one item per document instead of one per page; upgrading docling versions where a stage model's return contract changed; experimental models that lazily skip failed pages instead of returning a failure payload.","solutions":["Make the custom stage model return exactly one result per page it is given, including error/empty payloads for pages it could not process.","If you don't need custom models, remove any monkey-patching or overridden model classes so stock docling models are used.","Pin/align docling versions so stage models and pipeline code come from the same release.","Report the issue upstream if stock models with unmodified inputs trigger it, including the stage name in the message."],"exampleFix":"# before\nclass MyModel:\n    def __call__(self, conv_res, page_batch):\n        return [self._process_all_pages_once(conv_res, page_batch)]  # 1 result for N pages\n\n# after\nclass MyModel:\n    def __call__(self, conv_res, page_batch):\n        return [self._process_one(conv_res, p) for p in page_batch]  # N results for N pages","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    result = converter.convert(doc)\nexcept RuntimeError as e:\n    if 'wrong number of pages' in str(e):\n        # custom stage model broke the 1-result-per-page contract; fix the model\n        ...","preventionTips":["Custom stage models must return exactly one payload per input page.","Don't monkey-patch stock docling models in production code.","Keep docling and docling-core versions pinned together."],"tags":["pipeline","threading","custom-model","internal-invariant"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}