{"record":{"id":"e295b96c28a938bf","repo":"nicolargo/glances","slug":"item","errorCode":null,"errorMessage":"{item}","messagePattern":"\\{item\\}","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"glances/stats.py","lineNumber":59,"sourceCode":"\n    def __getattr__(self, item):\n        \"\"\"Overwrite the getattr method in case of attribute is not found.\n\n        The goal is to dynamically generate the following methods:\n        - getPlugname(): return Plugname stat in JSON format\n        - getViewsPlugname(): return views of the Plugname stat in JSON format\n        \"\"\"\n        # Check if the attribute starts with 'get'\n        if item.startswith('getViews'):\n            # Get the plugin name\n            plugname = item[len('getViews') :].lower()\n            # Get the plugin instance\n            plugin = self._plugins[plugname]\n            if hasattr(plugin, 'get_json_views'):\n                # The method get_json_views exist, return it\n                return getattr(plugin, 'get_json_views')\n            # The method get_views is not found for the plugin\n            raise AttributeError(item)\n        if item.startswith('get'):\n            # Get the plugin name\n            plugname = item[len('get') :].lower()\n            # Get the plugin instance\n            plugin = self._plugins[plugname]\n            if hasattr(plugin, 'get_json'):\n                # The method get_json exist, return it\n                return getattr(plugin, 'get_json')\n            # The method get_stats is not found for the plugin\n            raise AttributeError(item)\n        # Default behavior\n        raise AttributeError(item)\n\n    def load_modules(self, args):\n        \"\"\"Wrapper to load: plugins and export modules.\"\"\"\n\n        # Init the plugins dict\n        # Active plugins dictionary","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/nicolargo/glances/blob/a240d8dfb3105a38b5964357ec21768594b0e83e/glances/stats.py#L41-L77","documentation":"AttributeError raised by GlancesStats.__getattr__ (glances/stats.py:59) when code calls get_pluginsXXX_views()-style accessors: it resolves plugname from the attribute name, finds the plugin, but the plugin has no get_json_views method, so the fallback raises AttributeError(item). It is the dynamic plugin-dispatch protocol failing to find the expected method on the target plugin.","triggerScenarios":"Calling stats.get_XYZ_views (or any get..._views accessor) where plugin XYZ exists but doesn't implement get_json_views — e.g. a plugin not derived from the standard model, or a typo where the plugin name resolves to something unexpected.","commonSituations":"Custom plugins missing the views API; version mixes where an old plugin lacks get_json_views; typos in dynamically constructed method names.","solutions":["Verify the target plugin class implements get_json_views (standard GlancesPluginModel subclasses do)","Fix the accessor name — it must match an actual loaded plugin name exactly","Update the custom plugin to inherit from Glances's plugin model","Catch AttributeError around dynamic dispatch and skip that plugin"],"exampleFix":"# before\nviews = stats.get_myplugin_views()\n# after\nfn = getattr(stats, 'get_myplugin_views', None)\nviews = fn() if fn else {}","handlingStrategy":"type-guard","validationCode":"fn = getattr(stats, f'get_{name}_views', None)\nviews = fn() if callable(fn) else {}","typeGuard":"def has_views_accessor(stats, plugin: str) -> bool:\n    return callable(getattr(stats, f'get_{plugin}_views', None))","tryCatchPattern":"try:\n    views = getattr(stats, f'get_{name}_views')()\nexcept AttributeError:\n    views = {}","preventionTips":["Build accessor names from the actual loaded plugin list","Derive custom plugins from the standard plugin model","Guard every dynamic get* dispatch with getattr defaults"],"tags":["glances","plugin","attribute-error","dynamic-dispatch"],"backgroundTag":"attribute-error-missing-method","analyzedSha":"a240d8dfb3105a38b5964357ec21768594b0e83e","analyzedAt":"2026-08-27T19:15:19.178Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}