PaddlePaddle/PaddleOCR · error · NotImplementedError

{} is not supported in MultiHead yet

Error message

{} is not supported in MultiHead yet

What it means

MultiHead is a composite head that builds a CTC branch (plus optional SAR/NRTR branch) by dispatching on the name key of each entry in the config's Head list. Only known names take a dedicated construction path; any other name reaches the else and raises NotImplementedError.

Source

Thrown at ppocr/modeling/heads/rec_multi_head.py:130

                    out_channels=out_channels_list["NRTRLabelDecode"],
                )
            elif name == "CTCHead":
                # ctc neck
                self.encoder_reshape = Im2Seq(in_channels)
                neck_args = self.head_list[idx][name]["Neck"]
                encoder_type = neck_args.pop("name")
                self.ctc_encoder = SequenceEncoder(
                    in_channels=in_channels, encoder_type=encoder_type, **neck_args
                )
                # ctc head
                head_args = self.head_list[idx][name]["Head"]
                self.ctc_head = eval(name)(
                    in_channels=self.ctc_encoder.out_channels,
                    out_channels=out_channels_list["CTCLabelDecode"],
                    **head_args,
                )
            else:
                raise NotImplementedError(
                    "{} is not supported in MultiHead yet".format(name)
                )

    def forward(self, x, targets=None):
        if self.use_pool:
            x = self.pool(
                x.reshape([0, 3, -1, self.in_channels]).transpose([0, 3, 1, 2])
            )
        ctc_encoder = self.ctc_encoder(x)
        ctc_out = self.ctc_head(ctc_encoder, targets)
        head_out = dict()
        head_out["ctc"] = ctc_out
        head_out["ctc_neck"] = ctc_encoder
        # eval mode
        if not self.training:
            return ctc_out
        if self.gtc_head == "sar":
            sar_out = self.sar_head(x, targets[1:])

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Set each entry's name to "Multi" (CTC + optional SAR) or "SRNHead" exactly as MultiHead expects; check the canonical Multi config templates under configs/rec for the exact structure
  2. If you genuinely need a new head type inside MultiHead, add an elif branch in ppocr/modeling/heads/rec_multi_head.py that constructs it, mirroring the SRNHead path
  3. Print self.head_list in __init__ to confirm the parsed structure matches what you wrote in YAML

Example fix

# before (config yml)
Head:
  name: Multi
  Head list:
    - name: CTCHead   # not supported
      Head: ...
# after
Head:
  name: Multi
  Head list:
    - name: Multi     # CTC branch built by SequenceEncoder path
      Head: ...
    - name: SARHead
      Head: ...
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED = {"Multi", "SRNHead"}
def validate_head_list(head_list):
    names = [entry.get('name') if isinstance(entry, dict) else entry for entry in head_list]
    bad = [n for n in names if n not in SUPPORTED]
    if bad:
        raise ValueError(f'MultiHead does not support head names {bad}; supported: {sorted(SUPPORTED)}')

Type guard

def is_supported_head_name(name) -> bool:
    return isinstance(name, str) and name in {'Multi', 'SRNHead'}

Try / catch

try:
    model = build_model(cfg)
except NotImplementedError as e:
    if 'not supported in MultiHead' in str(e):
        raise ValueError(f'check Head list names in config: {e}') from e
    raise

Prevention

When it happens

Trigger: Configuring Multi with a Head list whose name is neither "Multi" nor "SRNHead" (those are the two dispatched names in __init__), e.g. name: "CTCHead", "NRHead", "Multi1", or a typo like "multi".

Common situations: Converting a single-head rec config to the Multi template and leaving the old head name in place; renaming heads during an upgrade; YAML indentation putting the name key at the wrong level so it is read as an unknown value.

Related errors


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