{"record":{"id":"35cdf6394abd87d7","repo":"apache/beam","slug":"s-object-has-no-attribute-s","errorCode":null,"errorMessage":"'%s' object has no attribute '%s'","messagePattern":"'(.+?)' object has no attribute '(.+?)'","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/options/pipeline_options.py","lineNumber":704,"sourceCode":"    return tuple(map(int, v1_parts)) < tuple(map(int, v2_parts))\n\n  def _visible_option_list(self) -> list[str]:\n    return sorted(\n        option for option in dir(self._visible_options) if option[0] != '_')\n\n  def __dir__(self) -> list[str]:\n    return sorted(\n        dir(type(self)) + list(self.__dict__) + self._visible_option_list())\n\n  def __getattr__(self, name):\n    # Special methods which may be accessed before the object is\n    # fully constructed (e.g. in unpickling).\n    if name[:2] == name[-2:] == '__':\n      return object.__getattribute__(self, name)\n    elif name in self._visible_option_list():\n      return self._all_options[name]\n    else:\n      raise AttributeError(\n          \"'%s' object has no attribute '%s'\" % (type(self).__name__, name))\n\n  def __setattr__(self, name, value):\n    if name in ('_flags', '_all_options', '_visible_options'):\n      super().__setattr__(name, value)\n    elif name in self._visible_option_list():\n      self._all_options[name] = value\n    else:\n      raise AttributeError(\n          \"'%s' object has no attribute '%s'\" % (type(self).__name__, name))\n\n  def __str__(self):\n    return '%s(%s)' % (\n        type(self).__name__,\n        ', '.join(\n            '%s=%s' % (option, getattr(self, option))\n            for option in self._visible_option_list()))\n","sourceCodeStart":686,"sourceCodeEnd":722,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/options/pipeline_options.py#L686-L722","documentation":"PipelineOptions.__getattr__ forwards attribute access to parsed option values; if the name is not among the visible options for this options class, AttributeError is raised. This means the option was never defined by this PipelineOptions subclass or was not parsed.","triggerScenarios":"Accessing options.some_flag where some_flag is not a registered option of the view class, e.g. options.view_as(GoogleCloudOptions).my_custom_option, or accessing an option before it exists during unpickling.","commonSituations":"Typo in the option name, reading an option from the wrong view class, or custom options added without a _add_ method/annotation on the subclass.","solutions":["Use view_as with the correct options class that defines the attribute.","Fix the attribute-name typo to match the option's getter name.","Define custom options properly in a PipelineOptions subclass via class annotations."],"exampleFix":"# before\nrunner = options.project_id  # wrong attribute on base class\n# after\nfrom apache_beam.options.pipeline_options import GoogleCloudOptions\nproject_id = options.view_as(GoogleCloudOptions).project_id","handlingStrategy":"type-guard","validationCode":"if not hasattr(options.view_as(GoogleCloudOptions), 'project_id'): ...","typeGuard":"def has_option(opts, name: str) -> bool:\n    return name in opts.get_all_options(drop_default=True) or hasattr(opts.view_as(type(opts)), name)","tryCatchPattern":"try:\n    val = options.my_option\nexcept AttributeError:\n    val = None  # or use options.get_all_options() to inspect available keys","preventionTips":["Use view_as(ExactOptionsClass) and rely on typed getters instead of raw attributes.","Inspect options.get_all_options() to discover valid option names.","Register custom options via a PipelineOptions subclass."],"tags":["apache-beam","python","attribute-error"],"backgroundTag":"missing-required-option","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}