PaddlePaddle/PaddleOCR · error · ValueError

`decoder_start_token_id` expected to have length {batch_size

Error message

`decoder_start_token_id` expected to have length {batch_size} but got {len(decoder_start_token_id)}

What it means

decoder_start_token_id may be a per-sample list, in which case it must have exactly batch_size entries so each sequence in the batch starts from its own token. The helper validates len(decoder_start_token_id) == batch_size before converting the list to a tensor.

Source

Thrown at ppocr/modeling/heads/rec_unimernet_head.py:2178

        batch_size,
        model_kwargs,
        decoder_start_token_id=None,
        bos_token_id=None,
    ):
        if model_kwargs is not None and "decoder_input_ids" in model_kwargs:
            decoder_input_ids = model_kwargs.pop("decoder_input_ids")
        elif "input_ids" in model_kwargs:
            decoder_input_ids = model_kwargs.pop("input_ids")
        else:
            decoder_input_ids = None

        decoder_start_token_id = self._get_decoder_start_token_id(
            decoder_start_token_id, bos_token_id
        )

        if isinstance(decoder_start_token_id, list):
            if len(decoder_start_token_id) != batch_size:
                raise ValueError(
                    f"`decoder_start_token_id` expected to have length {batch_size} but got {len(decoder_start_token_id)}"
                )
            decoder_input_ids_start = paddle.to_tensor(
                decoder_start_token_id,
                dtype=paddle.int64,
            )
            decoder_input_ids_start = decoder_input_ids_start.view(-1, 1)
        else:
            decoder_input_ids_start = (
                paddle.ones(
                    (batch_size, 1),
                    dtype=paddle.int64,
                )
                * decoder_start_token_id
            )

        if decoder_input_ids is None:
            decoder_input_ids = decoder_input_ids_start

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Pass a single int start token if all samples share it
  2. Or build the list dynamically: [start_ids[i % len(start_ids)] for i in range(batch_size)] / tile to batch_size
  3. Verify input batch size before generate and align the list length

Example fix

# before
decoder_start_token_id = [1, 2]  # batch is 4
# after
decoder_start_token_id = [1, 2, 1, 2]  # or just 1
Defensive patterns

Strategy: validation

Validate before calling

if isinstance(decoder_start_token_id, list):
    assert len(decoder_start_token_id) == batch_size, 'start ids must match batch size'
# or normalize:
if isinstance(decoder_start_token_id, int):
    decoder_start_token_id = [decoder_start_token_id] * batch_size

Type guard

def start_ids_match(start_ids, batch_size: int) -> bool:
    return not isinstance(start_ids, list) or len(start_ids) == batch_size

Prevention

When it happens

Trigger: Providing a list of start ids shorter/longer than the batch, e.g. hardcoding one id while running batch inference, or passing a python range of ids of the wrong length.

Common situations: Prompt-batched decoding where each sample needs a distinct start token; mismatch between dataloader batch size and a fixed start-token list.

Related errors


AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14). Data as JSON: /api/errors/e01a12368d40dc62. Report an issue: GitHub.