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
- Regenerate the label file so each annotation includes "key_cls": <class_id> (integer), e.g. {"transcription": "TOTAL", "points": [...], "key_cls": 5}
- 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
- Sanity-check a few lines: python -c 'import json; [print(json.loads(l)[0].keys()) for l in open("train_label.txt")][:3]'
- 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
- Run a label-file lint step (check keys of every JSON annotation) before training
- Keep the class_list_file next to the labels and version them together
- Automate KIE label conversion from raw annotations instead of hand-editing
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
- The input data is inconsistent with expectations.
- Expected float between 0 and 1 pct_start, but got {}
- anneal_strategy must by one of 'cos' or 'linear', instead go
- Tried to step {} times. The specified number of total steps
- The type of 'T_max1' in 'CosineAnnealingDecay' must be 'int'
AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14).
Data as JSON: /api/errors/c1016894763d0398.
Report an issue: GitHub.