PaddlePaddle/PaddleOCR · error · TypeError

The norm_layer must be str or paddle.nn.layer.Layer class

Error message

The norm_layer must be str or paddle.nn.layer.Layer class

What it means

Second norm guard in the same CPPD Block.__init__, building self.norm2 (norm before the MLP): same contract — norm_layer must be str or Callable, else TypeError('The norm_layer must be str or paddle.nn.layer.Layer class'). Because it re-checks the identical argument after the norm1/normkv guard already passed, this specific line is effectively unreachable in the shipped code; it would only fire in a fork where norm1 and norm2 receive different values.

Source

Thrown at ppocr/modeling/heads/rec_cppd_head.py:193

        else:
            raise TypeError("The norm_layer must be str or paddle.nn.LayerNorm class")
        self.mixer = Attention(
            dim,
            num_heads=num_heads,
            qkv_bias=qkv_bias,
            qk_scale=qk_scale,
            attn_drop=attn_drop,
            proj_drop=drop,
        )

        # NOTE: drop path for stochastic depth, we shall see if this is better than dropout here
        self.drop_path = DropPath(drop_path) if drop_path > 0.0 else Identity()
        if isinstance(norm_layer, str):
            self.norm2 = eval(norm_layer)(dim, epsilon=epsilon)
        elif isinstance(norm_layer, Callable):
            self.norm2 = norm_layer(dim)
        else:
            raise TypeError("The norm_layer must be str or paddle.nn.layer.Layer class")
        mlp_hidden_dim = int(dim * mlp_ratio)
        self.mlp_ratio = mlp_ratio
        self.mlp = Mlp(
            in_features=dim,
            hidden_features=mlp_hidden_dim,
            act_layer=act_layer,
            drop=drop,
        )

    def forward(self, q, kv):
        x1 = self.norm1(q + self.drop_path(self.mixer(q, kv)))
        x = self.norm2(x1 + self.drop_path(self.mlp(x1)))
        return x


class CPPDHead(nn.Layer):
    def __init__(
        self,

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Same as the norm1 guard: pass norm_layer as a class or string
  2. In modified code, validate any second norm argument with the same isinstance(str/Callable) check before use

Example fix

// not applicable (duplicate guard; fix norm_layer as in the norm1 error)
null
Defensive patterns

Strategy: type-guard

Validate before calling

assert isinstance(norm_layer, (str, Callable)), 'norm_layer must be a str or Callable class'

Type guard

from collections.abc import Callable

def is_valid_norm_layer(n) -> bool:
    return isinstance(n, (str, Callable)) and not isinstance(n, nn.Layer)

Prevention

When it happens

Trigger: Not reachable via the public constructor since the identical value already passed the first isinstance chain two statements earlier; would trigger only if a modified version supplies a separate, invalid norm argument for the MLP branch.

Common situations: Local forks adding independent pre-attention/pre-MLP norm configuration and passing an instance or None only for the second one.

Related errors


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