PaddlePaddle/PaddleOCR · error · ValueError

Incorrect 4D attention_mask shape: {tuple(attention_mask.sha

Error message

Incorrect 4D attention_mask shape: {tuple(attention_mask.shape)}; expected: {expected_shape}.

What it means

The decoder accepts a user-supplied 4D attention mask but validates its shape strictly: it must be exactly (batch_size, 1, query_len, key_value_length). A mask of any other rank-4 shape (wrong batch dim, extra heads, swapped q/kv axes, or stale kv length) raises this ValueError.

Source

Thrown at ppocr/modeling/heads/rec_ppformulanet_head.py:335

    )

    key_value_length = input_shape[-1] + past_key_values_length

    # 4d mask is passed through the layers
    if attention_mask is not None and len(attention_mask.shape) == 2:
        attention_mask = attn_mask_converter.to_4d(
            attention_mask,
            input_shape[-1],
            key_value_length=key_value_length,
            dtype=inputs_embeds.dtype,
            use_parallel=use_parallel,
            parallel_step=parallel_step,
            is_export=is_export,
        )
    elif attention_mask is not None and len(attention_mask.shape) == 4:
        expected_shape = (input_shape[0], 1, input_shape[1], key_value_length)
        if tuple(attention_mask.shape) != expected_shape:
            raise ValueError(
                f"Incorrect 4D attention_mask shape: {tuple(attention_mask.shape)}; expected: {expected_shape}."
            )
        else:
            # if the 4D mask has correct shape - invert it and fill with negative infinity
            inverted_mask = 1.0 - attention_mask
            attention_mask = inverted_mask.masked_fill_(
                inverted_mask.to(paddle.bool), paddle.finfo(inputs_embeds.dtype).min
            )
    else:
        attention_mask = attn_mask_converter.to_causal_4d(
            input_shape[0],
            input_shape[-1],
            key_value_length,
            dtype=inputs_embeds.dtype,
        )

    return attention_mask

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Build the 4D mask with exactly (batch, 1, q_len, kv_len); prefer passing a 2D (batch, seq) padding mask and letting to_4d handle expansion
  2. Inside generation loops, rebuild or slice the mask each step so the last dim tracks the growing kv length
  3. Check attention_mask.shape[0] equals input batch and shape[2] equals current query length before the call

Example fix

# before
attn_mask = my_mask  # shape (B, num_heads, L, L)
# after - pass 2D and let the model expand
attn_mask = padding_mask  # shape (B, L) of 0/1
Defensive patterns

Strategy: type-guard

Validate before calling

def check_4d_mask(mask, batch, q_len, kv_len):
    expected = (batch, 1, q_len, kv_len)
    if mask is not None and len(mask.shape) == 4 and tuple(mask.shape) != expected:
        raise ValueError(f'mask {tuple(mask.shape)} != expected {expected}; pass a 2D (B, L) mask instead')

Type guard

def is_valid_4d_mask(mask, batch, q_len, kv_len) -> bool:
    return mask is None or len(mask.shape) != 4 or tuple(mask.shape) == (batch, 1, q_len, kv_len)

Try / catch

try:
    out = decoder(attention_mask=mask, ...)
except ValueError as e:
    if 'Incorrect 4D attention_mask shape' in str(e):
        out = decoder(attention_mask=mask_2d, ...)  # fall back to 2D
    else:
        raise

Prevention

When it happens

Trigger: Passing attention_mask with shape (B, H, L, L) with H != 1, (B, 1, kv_len, q_len) transposed, or a mask built for a previous step whose kv length no longer matches during cached/parallel decoding.

Common situations: Feeding a multi-head mask from another HF-style model into this decoder; precomputing masks once outside a generation loop while key_value_length grows each step; batching inputs of mixed lengths with a manually tiled mask.

Related errors


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