{"record":{"id":"a3e706e431068c70","repo":"pandas-dev/pandas","slug":"you-can-only-set-the-value-of-existing-options","errorCode":null,"errorMessage":"You can only set the value of existing options","messagePattern":"You can only set the value of existing options","errorType":"exception","errorClass":"OptionError","httpStatus":null,"severity":"error","filePath":"pandas/_config/config.py","lineNumber":428,"sourceCode":"    \"\"\"provide attribute-style access to a nested dict\"\"\"\n\n    d: dict[str, Any]\n\n    def __init__(self, d: dict[str, Any], prefix: str = \"\") -> None:\n        object.__setattr__(self, \"d\", d)\n        object.__setattr__(self, \"prefix\", prefix)\n\n    def __setattr__(self, key: str, val: Any) -> None:\n        prefix = object.__getattribute__(self, \"prefix\")\n        if prefix:\n            prefix += \".\"\n        prefix += key\n        # you can't set new keys\n        # can you can't overwrite subtrees\n        if key in self.d and not isinstance(self.d[key], dict):\n            set_option(prefix, val)\n        else:\n            raise OptionError(\"You can only set the value of existing options\")\n\n    def __getattr__(self, key: str) -> Any:\n        prefix = object.__getattribute__(self, \"prefix\")\n        if prefix:\n            prefix += \".\"\n        prefix += key\n        try:\n            v = object.__getattribute__(self, \"d\")[key]\n        except KeyError as err:\n            raise OptionError(\"No such option\") from err\n        if isinstance(v, dict):\n            return DictWrapper(v, prefix)\n        else:\n            return get_option(prefix)\n\n    def __dir__(self) -> list[str]:\n        return list(self.d.keys())\n","sourceCodeStart":410,"sourceCodeEnd":446,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/_config/config.py#L410-L446","documentation":"Raised by DictWrapper.__setattr__ (config.py:418-428) when assigning an attribute that is not an existing leaf option. The attribute-style API (pd.options.display.x = v) only supports overwriting existing values, never creating new keys or subtrees.","triggerScenarios":"pd.options.display.new_thing = 5, or assigning into a namespace prefix (pd.options.display = {...}) where 'display' maps to a sub-dict, not a leaf.","commonSituations":"Assuming pd.options behaves like a plain dict and trying to add a custom setting via attribute assignment.","solutions":["Register the option first with cf.register_option('display.new_thing', 5).","Set existing options via set_option('display.new_thing', 5) once registered.","Use the attribute API only for keys already present in pd.describe_option()."],"exampleFix":"# before\npd.options.display.my_width = 100  # You can only set the value of existing options\n\n# after\nimport pandas._config.config as cf\ncf.register_option('display.my_width', 100, validator=cf.is_int)\npd.options.display.my_width = 200","handlingStrategy":"validation","validationCode":"def set_attr_option(root, key, value):\n    # root is e.g. pd.options.display; verify key is an existing leaf\n    if key not in dir(root) or isinstance(getattr(root, key, None), type(root)):\n        raise AttributeError(f'{key} is not an existing option on {root}')\n    setattr(root, key, value)","typeGuard":"def is_settable_leaf(root, key: str) -> bool:\n    d = object.__getattribute__(root, 'd')\n    return key in d and not isinstance(d[key], dict)","tryCatchPattern":"from pandas.errors import OptionError\ntry:\n    setattr(pd.options.display, key, value)\nexcept OptionError:\n    print(f'{key} is not registered; call register_option first')","preventionTips":["Reserve pd.options attribute assignment to known leaf options only.","Use set_option/register_option for any new custom setting.","Document which options your library expects users to set."],"tags":["config","options-attribute","setattr"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}