{"record":{"id":"2f2e5b706de756fa","repo":"kovidgoyal/kitty","slug":"no-option-named-k-2f2e5b","errorCode":null,"errorMessage":"No option named: {k}","messagePattern":"No option named: (.+?)","errorType":"validation","errorClass":"KeyError","httpStatus":null,"severity":"error","filePath":"kitty/options/types.py","lineNumber":839,"sourceCode":"\n    def _asdict(self) -> dict[str, typing.Any]:\n        return {k: self._copy_of_val(k) for k in self}\n\n    def _replace(self, **kw: typing.Any) -> \"Options\":\n        ans = Options()\n        for name in self:\n            setattr(ans, name, self._copy_of_val(name))\n        for name, val in kw.items():\n            setattr(ans, name, val)\n        return ans\n\n    def __getitem__(self, key: int | str) -> typing.Any:\n        k = option_names[key] if isinstance(key, int) else key\n        try:\n            return getattr(self, k)\n        except AttributeError:\n            pass\n        raise KeyError(f\"No option named: {k}\")\n\n    def __getattr__(self, key: str) -> typing.Any:\n        if key.startswith(\"color\"):\n            q = key[5:]\n            if q.isdigit():\n                k = int(q)\n                if 0 <= k <= 255:\n                    x = self.color_table[k]\n                    if x == 0xffffffff:\n                        return None\n                    return Color((x >> 16) & 255, (x >> 8) & 255, x & 255)\n        raise AttributeError(key)\n\n    def __setattr__(self, key: str, val: typing.Any) -> typing.Any:\n        if key.startswith(\"color\"):\n            q = key[5:]\n            if q.isdigit():\n                k = int(q)","sourceCodeStart":821,"sourceCodeEnd":857,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kitty/options/types.py#L821-L857","documentation":"kitty's Options object maps option names to attributes; __getitem__ converts integer keys via option_names then does getattr. If the attribute does not exist and the key is not a colorN index (handled by __getattr__), it raises KeyError 'No option named: <k>'.","triggerScenarios":"Calling opts['nonexistent_option'] or opts[bad_index] on a kitty Options instance — e.g. opts['font_sizee'], or indexing with an int whose option_names lookup yields an undefined name. Also hit by code assuming an option exists in the running kitty version.","commonSituations":"Plugins/remote-control code referencing options renamed or added in a different kitty version; typos in option names; using an int index out of range for option_names.","solutions":["Check the exact option name against kitty/options/types.py or `kitty +runpy` introspection","Guard access with `if hasattr(opts, name)` or use opts.get-style patterns","If version-dependent, gate the access on the kitty version or feature detection"],"exampleFix":"# before\nval = opts['allow_hyperlinks']  # AttributeError->KeyError if absent\n# after\nval = getattr(opts, 'allow_hyperlinks', None)","handlingStrategy":"try-catch","validationCode":"from kitty.options.types import Options\nname = 'some_option'\nif not hasattr(opts, name) and not (name.startswith('color') and name[5:].isdigit()):\n    print(f'unknown option: {name}')","typeGuard":"def option_exists(opts, name: str) -> bool:\n    try:\n        _ = opts[name]\n        return True\n    except KeyError:\n        return False","tryCatchPattern":"try:\n    val = opts[name]\nexcept KeyError:\n    val = default  # or skip feature","preventionTips":["Feature-detect options before use across kitty versions","Prefer getattr(opts, name, default) for optional lookups"],"tags":["kitty","options","key-error","lookup"],"backgroundTag":"dict-key-missing","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}