{"record":{"id":"c18d91d548a8ac44","repo":"opendatalab/MinerU","slug":"pp-doclayoutv2-reading-order-inference-requires-a","errorCode":null,"errorMessage":"PP-DocLayoutV2 reading-order inference requires a mask tensor.","messagePattern":"PP-DocLayoutV2 reading-order inference requires a mask tensor\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mineru/model/layout/pp_doclayoutv2.py","lineNumber":738,"sourceCode":"    config_class = PPDocLayoutV2ReadingOrderConfig\n\n    def __init__(self, config: PPDocLayoutV2ReadingOrderConfig):\n        super().__init__(config)\n        self.embeddings = PPDocLayoutV2TextEmbeddings(config)\n        self.label_embeddings = nn.Embedding(config.num_classes, config.hidden_size)\n        self.label_features_projection = nn.Linear(config.hidden_size, config.hidden_size)\n        self.encoder = PPDocLayoutV2ReadingOrderEncoder(config)\n        self.relative_head = PPDocLayoutV2GlobalPointer(config)\n        self.post_init()\n\n    def forward(\n        self,\n        boxes: torch.Tensor,\n        labels: Optional[torch.Tensor] = None,\n        mask: Optional[torch.Tensor] = None,\n    ) -> torch.Tensor:\n        if mask is None:\n            raise ValueError(\"PP-DocLayoutV2 reading-order inference requires a mask tensor.\")\n\n        device = mask.device\n        batch_size, seq_len = mask.shape\n        num_pred = mask.sum(dim=1)\n\n        input_ids = torch.full(\n            (batch_size, seq_len + 2),\n            self.config.pad_token_id,\n            dtype=torch.long,\n            device=device,\n        )\n        input_ids[:, 0] = self.config.start_token_id\n        pred_col_idx = torch.arange(seq_len + 2, device=device).unsqueeze(0)\n        pred_mask = (pred_col_idx >= 1) & (pred_col_idx <= num_pred.unsqueeze(1))\n        input_ids[pred_mask] = self.config.pred_token_id\n        input_ids[torch.arange(batch_size, device=device), num_pred + 1] = self.config.end_token_id\n\n        pad_box = torch.zeros((batch_size, 1, boxes.shape[-1]), dtype=boxes.dtype, device=device)","sourceCodeStart":720,"sourceCodeEnd":756,"githubUrl":"https://github.com/opendatalab/MinerU/blob/4fe4bde114a23ee5dd637eae99b767f4669bf58c/mineru/model/layout/pp_doclayoutv2.py#L720-L756","documentation":"ValueError raised at the top of PPDocLayoutV2(ReadingOrder)Model.forward when the mask argument is None. The inference path derives batch_size and seq_len from mask.shape and uses mask.sum(dim=1) to count predictions, so unlike typical optional HF-style masks, here the mask is mandatory.","triggerScenarios":"Calling model(boxes) or model(boxes, labels=None, mask=None) — omitting the mask or explicitly passing None; code ported from another model where attention_mask was optional and simply not supplied.","commonSituations":"New integrations assuming HF conventions where masks default to all-ones; refactors that dropped the mask argument; test code calling forward with only boxes.","solutions":["Pass a 2D mask of shape [batch, seq_len] with 1 for real boxes and 0 for padding.","If you have no padding, build torch.ones(boxes.shape[0], boxes.shape[1], dtype=torch.long, device=boxes.device).","Check the model's docstring/signature — mask is required for this model, not optional."],"exampleFix":"# before\nout = model(boxes)  # ValueError: requires a mask tensor\n\n# after\nmask = torch.ones(boxes.shape[0], boxes.shape[1], dtype=torch.long, device=boxes.device)\nout = model(boxes, mask=mask)","handlingStrategy":"validation","validationCode":"import torch\n\ndef required_mask(boxes: torch.Tensor) -> torch.Tensor:\n    # 1 for real boxes, 0 for padding — derive shape from boxes itself\n    return torch.ones(boxes.shape[0], boxes.shape[1], dtype=torch.long, device=boxes.device)\n\nout = model(boxes, mask=required_mask(boxes))","typeGuard":"def has_valid_mask(mask, boxes) -> bool:\n    import torch\n    return (\n        isinstance(mask, torch.Tensor)\n        and mask.ndim == 2\n        and mask.shape == (boxes.shape[0], boxes.shape[1])\n    )","tryCatchPattern":null,"preventionTips":["Treat mask as a required argument for this model despite HF conventions.","Build the mask from the boxes tensor's own shape at the call site.","Wrap model calls in a small adapter function that always supplies the mask."],"tags":["pytorch","deep-learning","required-argument","layout-model"],"backgroundTag":null,"analyzedSha":"4fe4bde114a23ee5dd637eae99b767f4669bf58c","analyzedAt":"2026-08-14T21:29:18.456Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}