{"record":{"id":"225e45b17dc2daa3","repo":"WZMIAOMIAO/deep-learning-for-image-processing","slug":"object-has-no-attribute-225e45","errorCode":null,"errorMessage":"'{}' object has no attribute '{}'","messagePattern":"'(.+?)' object has no attribute '(.+?)'","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"pytorch_object_detection/yolov3_spp/train_utils/distributed_utils.py","lineNumber":162,"sourceCode":"\nclass MetricLogger(object):\n    def __init__(self, delimiter=\"\\t\"):\n        self.meters = defaultdict(SmoothedValue)\n        self.delimiter = delimiter\n\n    def update(self, **kwargs):\n        for k, v in kwargs.items():\n            if isinstance(v, torch.Tensor):\n                v = v.item()\n            assert isinstance(v, (float, int))\n            self.meters[k].update(v)\n\n    def __getattr__(self, attr):\n        if attr in self.meters:\n            return self.meters[attr]\n        if attr in self.__dict__:\n            return self.__dict__[attr]\n        raise AttributeError(\"'{}' object has no attribute '{}'\".format(\n            type(self).__name__, attr))\n\n    def __str__(self):\n        loss_str = []\n        for name, meter in self.meters.items():\n            loss_str.append(\n                \"{}: {}\".format(name, str(meter))\n            )\n        return self.delimiter.join(loss_str)\n\n    def synchronize_between_processes(self):\n        for meter in self.meters.values():\n            meter.synchronize_between_processes()\n\n    def add_meter(self, name, meter):\n        self.meters[name] = meter\n\n    def log_every(self, iterable, print_freq, header=None):","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/WZMIAOMIAO/deep-learning-for-image-processing/blob/1ec3fe6f374fc9969973a61f819de25658595afa/pytorch_object_detection/yolov3_spp/train_utils/distributed_utils.py#L144-L180","documentation":"MeterLibrary (the averaged-meters container) implements __getattr__ that looks the attribute up in self.meters, then self.__dict__, and finally raises AttributeError naming the type and missing attribute. It means you accessed e.g. library.some_metric when no meter with that name was registered (or was registered under a different key).","triggerScenarios":"Accessing an attribute on the meter wrapper (e.g. in distributed_utils or the training loop like metric_logger.loss) when self.meters has no key with that exact name — meter never created via meter_library.update(..., n=...) or misspelled key.","commonSituations":"Typo in the metric name at access time vs update time; reading a meter before the first update call registered it; code copied between models that track different loss names.","solutions":["Confirm the meter was registered: call meter_library.update(loss_name=value) before reading it.","Print meter_library.meters.keys() to see the exact registered names and fix the access spelling.","Guard access with hasattr(meter_library, 'loss') or use meter_library.meters.get('loss') to avoid AttributeError."],"exampleFix":"// before\nprint(metric_logger.lr, metric_logger.los)\n// after\nprint(metric_logger.lr, metric_logger.loss)","handlingStrategy":"type-guard","validationCode":"known = set(metric_logger.meters.keys())\nassert 'loss' in known, f\"meter not registered; have: {known}\"","typeGuard":"def has_meter(lib, name: str) -> bool:\n    return name in getattr(lib, 'meters', {})","tryCatchPattern":"try:\n    avg_loss = metric_logger.loss\nexcept AttributeError:\n    avg_loss = float('nan')  # or register the meter before reading","preventionTips":["Read metric names from the same constants used at update() time","Log meters.keys() at epoch start during debugging","Avoid stringly-typed metric names; centralize them in one place"],"tags":["attribute-error","metrics","typo","training"],"backgroundTag":"missing-attribute-on-meter-container","analyzedSha":"1ec3fe6f374fc9969973a61f819de25658595afa","analyzedAt":"2026-08-30T09:19:11.901Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}