{"record":{"id":"5777858c50e69d01","repo":"PaddlePaddle/PaddleOCR","slug":"you-cannot-use-setdefault-on-a-self-class","errorCode":null,"errorMessage":"You cannot use ``setdefault`` on a {self.__class__.__name__} instance.","messagePattern":"You cannot use ``setdefault`` on a (.+?) instance\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"warning","filePath":"ppocr/modeling/heads/rec_unimernet_head.py","lineNumber":111,"sourceCode":"                        break\n                    setattr(self, element[0], element[1])\n                    if element[1] is not None:\n                        self[element[0]] = element[1]\n            elif first_field is not None:\n                self[class_fields[0].name] = first_field\n        else:\n            for field in class_fields:\n                v = getattr(self, field.name)\n                if v is not None:\n                    self[field.name] = v\n\n    def __delitem__(self, *args, **kwargs):\n        raise Exception(\n            f\"You cannot use ``__delitem__`` on a {self.__class__.__name__} instance.\"\n        )\n\n    def setdefault(self, *args, **kwargs):\n        raise Exception(\n            f\"You cannot use ``setdefault`` on a {self.__class__.__name__} instance.\"\n        )\n\n    def pop(self, *args, **kwargs):\n        raise Exception(\n            f\"You cannot use ``pop`` on a {self.__class__.__name__} instance.\"\n        )\n\n    def update(self, *args, **kwargs):\n        raise Exception(\n            f\"You cannot use ``update`` on a {self.__class__.__name__} instance.\"\n        )\n\n    def __getitem__(self, k):\n        if isinstance(k, str):\n            inner_dict = dict(self.items())\n            return inner_dict[k]\n        else:","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/ppocr/modeling/heads/rec_unimernet_head.py#L93-L129","documentation":"ModelOutput blocks setdefault because it could insert keys that are not declared dataclass fields, breaking the invariant that the dict view mirrors the typed attributes. The call always raises.","triggerScenarios":"Calling output.setdefault('key', default) on a ModelOutput returned by the UniMERNet head, e.g. in generic code that normalizes dict-like results.","commonSituations":"Shared post-processing helpers that call setdefault on anything dict-like; merging outputs from multiple models; caching wrappers that ensure a key exists before use.","solutions":["Use explicit conditional assignment on attributes: if output.key is None: output.key = default","Use output[k] if k in output else default when reading","Convert to a plain dict before running dict-oriented utilities"],"exampleFix":"# before\nout.setdefault('loss', 0.0)\n# after\nif out.loss is None:\n    out.loss = 0.0  # or construct a new ModelOutput with loss=0.0","handlingStrategy":"type-guard","validationCode":"def safe_get(output, key, default=None):\n    return output[key] if key in output else default\n# use safe_get(out, 'loss', 0.0) instead of out.setdefault('loss', 0.0)","typeGuard":"def is_model_output(obj) -> bool:\n    return hasattr(obj, '__dataclass_fields__') and hasattr(obj, 'to_tuple')","tryCatchPattern":"null  # design guard; use conditional attribute assignment instead","preventionTips":["Replace setdefault with 'if getattr(out, k, None) is None: out.k = default'","Convert to dict before running dict-oriented helper libraries","Keep a project note that ModelOutput blocks mutating dict methods"],"tags":["model-output","immutable","unimernet","api-misuse"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}