{"record":{"id":"436962dcbafd3728","repo":"PaddlePaddle/PaddleOCR","slug":"incorrect-4d-attention-mask-shape-tuple-attentio","errorCode":null,"errorMessage":"Incorrect 4D attention_mask shape: {tuple(attention_mask.shape)}; expected: {expected_shape}.","messagePattern":"Incorrect 4D attention_mask shape: (.+?); expected: (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"ppocr/modeling/heads/rec_ppformulanet_head.py","lineNumber":335,"sourceCode":"    )\n\n    key_value_length = input_shape[-1] + past_key_values_length\n\n    # 4d mask is passed through the layers\n    if attention_mask is not None and len(attention_mask.shape) == 2:\n        attention_mask = attn_mask_converter.to_4d(\n            attention_mask,\n            input_shape[-1],\n            key_value_length=key_value_length,\n            dtype=inputs_embeds.dtype,\n            use_parallel=use_parallel,\n            parallel_step=parallel_step,\n            is_export=is_export,\n        )\n    elif attention_mask is not None and len(attention_mask.shape) == 4:\n        expected_shape = (input_shape[0], 1, input_shape[1], key_value_length)\n        if tuple(attention_mask.shape) != expected_shape:\n            raise ValueError(\n                f\"Incorrect 4D attention_mask shape: {tuple(attention_mask.shape)}; expected: {expected_shape}.\"\n            )\n        else:\n            # if the 4D mask has correct shape - invert it and fill with negative infinity\n            inverted_mask = 1.0 - attention_mask\n            attention_mask = inverted_mask.masked_fill_(\n                inverted_mask.to(paddle.bool), paddle.finfo(inputs_embeds.dtype).min\n            )\n    else:\n        attention_mask = attn_mask_converter.to_causal_4d(\n            input_shape[0],\n            input_shape[-1],\n            key_value_length,\n            dtype=inputs_embeds.dtype,\n        )\n\n    return attention_mask\n","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/ppocr/modeling/heads/rec_ppformulanet_head.py#L317-L353","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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","Inside generation loops, rebuild or slice the mask each step so the last dim tracks the growing kv length","Check attention_mask.shape[0] equals input batch and shape[2] equals current query length before the call"],"exampleFix":"# before\nattn_mask = my_mask  # shape (B, num_heads, L, L)\n# after - pass 2D and let the model expand\nattn_mask = padding_mask  # shape (B, L) of 0/1","handlingStrategy":"type-guard","validationCode":"def check_4d_mask(mask, batch, q_len, kv_len):\n    expected = (batch, 1, q_len, kv_len)\n    if mask is not None and len(mask.shape) == 4 and tuple(mask.shape) != expected:\n        raise ValueError(f'mask {tuple(mask.shape)} != expected {expected}; pass a 2D (B, L) mask instead')","typeGuard":"def is_valid_4d_mask(mask, batch, q_len, kv_len) -> bool:\n    return mask is None or len(mask.shape) != 4 or tuple(mask.shape) == (batch, 1, q_len, kv_len)","tryCatchPattern":"try:\n    out = decoder(attention_mask=mask, ...)\nexcept ValueError as e:\n    if 'Incorrect 4D attention_mask shape' in str(e):\n        out = decoder(attention_mask=mask_2d, ...)  # fall back to 2D\n    else:\n        raise","preventionTips":["Prefer 2D padding masks; let the model build the 4D form","In generation loops, rebuild the mask every step as kv length grows","Assert mask.shape == (B, 1, q, kv) right before the decoder call"],"tags":["attention-mask","shape-validation","ppformulanet"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}