PaddlePaddle/PaddleOCR · error · ValueError

Cannot found 'key_cls' in ann.keys(), please check your trai

Error message

Cannot found 'key_cls' in ann.keys(), please check your training annotation.

What it means

During KIE (key information extraction) training, the label converter builds per-box class labels. For each annotation dict it first looks for a 'label' key (mapped through label2classid_map from the class_list file), then a 'key_cls' key used directly. If neither exists it raises ValueError telling you the training annotation is missing the class field.

Source

Thrown at ppocr/data/imaug/label_ops.py:435

            box = ann["points"]
            x_list = [box[i][0] for i in range(4)]
            y_list = [box[i][1] for i in range(4)]
            sorted_x_list, sorted_y_list = self.sort_vertex(x_list, y_list)
            sorted_box = []
            for x, y in zip(sorted_x_list, sorted_y_list):
                sorted_box.append(x)
                sorted_box.append(y)
            boxes.append(sorted_box)
            text = ann["transcription"]
            texts.append(ann["transcription"])
            text_ind = [self.dict[c] for c in text if c in self.dict]
            text_inds.append(text_ind)
            if "label" in ann.keys():
                labels.append(self.label2classid_map[ann["label"]])
            elif "key_cls" in ann.keys():
                labels.append(ann["key_cls"])
            else:
                raise ValueError(
                    "Cannot found 'key_cls' in ann.keys(), please check your training annotation."
                )
            edges.append(ann.get("edge", 0))
        ann_infos = dict(
            image=data["image"],
            points=boxes,
            texts=texts,
            text_inds=text_inds,
            edges=edges,
            labels=labels,
        )

        return self.list_to_numpy(ann_infos)


class AttnLabelEncode(BaseRecLabelEncode):
    """Convert between text-label and text-index"""

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Regenerate the label file so each annotation includes "key_cls": <class_id> (integer), e.g. {"transcription": "TOTAL", "points": [...], "key_cls": 5}
  2. Or add a "label" field with the class name and provide the matching class_list_file (e.g. train_data/class_list.txt) so label2classid_map can resolve it
  3. Sanity-check a few lines: python -c 'import json; [print(json.loads(l)[0].keys()) for l in open("train_label.txt")][:3]'
  4. Compare your label format against the wildreceipt annotation format shipped with the KIE docs

Example fix

// before (label line)
[{"transcription": "TOTAL", "points": [[1,2],[3,4]]}]
// after
[{"transcription": "TOTAL", "points": [[1,2],[3,4]], "key_cls": 1}]
Defensive patterns

Strategy: validation

Validate before calling

import json
for path in label_file_list:
    for line in open(path, encoding='utf-8'):
        anns = json.loads(line.strip())
        for ann in anns:
            if 'label' not in ann and 'key_cls' not in ann:
                raise SystemExit(f'{path}: annotation missing key_cls/label: {ann}')

Type guard

def is_valid_kie_annotation(ann: dict) -> bool:
    return ('transcription' in ann and 'points' in ann
            and ('label' in ann or 'key_cls' in ann))

Try / catch

try:
    batch = converter(annotations)
except ValueError as e:
    if 'key_cls' in str(e):
        raise ValueError(f'KIE label file lacks key_cls/label fields: {e}') from e
    raise

Prevention

When it happens

Trigger: Training a KIE model (e.g. SDMGR, configs/kie/) where the label file lines contain JSON annotations that have 'transcription' and 'points' but neither 'label' nor 'key_cls'.

Common situations: Using a plain OCR-format detection label file for KIE training; converting labels with a script that drops the key_cls field; wild-receipt dataset with custom preprocessing that renamed key_cls to something else.

Related errors


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