opendatalab/MinerU · error · ValueError

PP-DocLayoutV2 reading-order inference requires a mask tenso

Error message

PP-DocLayoutV2 reading-order inference requires a mask tensor.

What it means

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.

Source

Thrown at mineru/model/layout/pp_doclayoutv2.py:738

    config_class = PPDocLayoutV2ReadingOrderConfig

    def __init__(self, config: PPDocLayoutV2ReadingOrderConfig):
        super().__init__(config)
        self.embeddings = PPDocLayoutV2TextEmbeddings(config)
        self.label_embeddings = nn.Embedding(config.num_classes, config.hidden_size)
        self.label_features_projection = nn.Linear(config.hidden_size, config.hidden_size)
        self.encoder = PPDocLayoutV2ReadingOrderEncoder(config)
        self.relative_head = PPDocLayoutV2GlobalPointer(config)
        self.post_init()

    def forward(
        self,
        boxes: torch.Tensor,
        labels: Optional[torch.Tensor] = None,
        mask: Optional[torch.Tensor] = None,
    ) -> torch.Tensor:
        if mask is None:
            raise ValueError("PP-DocLayoutV2 reading-order inference requires a mask tensor.")

        device = mask.device
        batch_size, seq_len = mask.shape
        num_pred = mask.sum(dim=1)

        input_ids = torch.full(
            (batch_size, seq_len + 2),
            self.config.pad_token_id,
            dtype=torch.long,
            device=device,
        )
        input_ids[:, 0] = self.config.start_token_id
        pred_col_idx = torch.arange(seq_len + 2, device=device).unsqueeze(0)
        pred_mask = (pred_col_idx >= 1) & (pred_col_idx <= num_pred.unsqueeze(1))
        input_ids[pred_mask] = self.config.pred_token_id
        input_ids[torch.arange(batch_size, device=device), num_pred + 1] = self.config.end_token_id

        pad_box = torch.zeros((batch_size, 1, boxes.shape[-1]), dtype=boxes.dtype, device=device)

View on GitHub (pinned to 4fe4bde114)

Solutions

  1. Pass a 2D mask of shape [batch, seq_len] with 1 for real boxes and 0 for padding.
  2. If you have no padding, build torch.ones(boxes.shape[0], boxes.shape[1], dtype=torch.long, device=boxes.device).
  3. Check the model's docstring/signature — mask is required for this model, not optional.

Example fix

# before
out = model(boxes)  # ValueError: requires a mask tensor

# after
mask = torch.ones(boxes.shape[0], boxes.shape[1], dtype=torch.long, device=boxes.device)
out = model(boxes, mask=mask)
Defensive patterns

Strategy: validation

Validate before calling

import torch

def required_mask(boxes: torch.Tensor) -> torch.Tensor:
    # 1 for real boxes, 0 for padding — derive shape from boxes itself
    return torch.ones(boxes.shape[0], boxes.shape[1], dtype=torch.long, device=boxes.device)

out = model(boxes, mask=required_mask(boxes))

Type guard

def has_valid_mask(mask, boxes) -> bool:
    import torch
    return (
        isinstance(mask, torch.Tensor)
        and mask.ndim == 2
        and mask.shape == (boxes.shape[0], boxes.shape[1])
    )

Prevention

When it happens

Trigger: 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.

Common situations: New integrations assuming HF conventions where masks default to all-ones; refactors that dropped the mask argument; test code calling forward with only boxes.

Related errors


AI-assisted analysis of opendatalab/MinerU@4fe4bde114 (2026-08-14). Data as JSON: /api/errors/c18d91d548a8ac44. Report an issue: GitHub.