{"record":{"id":"700b23df52ae7765","repo":"kovidgoyal/kitty","slug":"no-option-named-k","errorCode":null,"errorMessage":"No option named: {k}","messagePattern":"No option named: (.+?)","errorType":"exception","errorClass":"KeyError","httpStatus":null,"severity":"error","filePath":"kitty/conf/generate.py","lineNumber":270,"sourceCode":"    a('        return {k: self._copy_of_val(k) for k in self}')\n\n    a('')\n    a('    def _replace(self, **kw: typing.Any) -> \"Options\":')\n    a('        ans = Options()')\n    a('        for name in self:')\n    a('            setattr(ans, name, self._copy_of_val(name))')\n    a('        for name, val in kw.items():')\n    a('            setattr(ans, name, val)')\n    a('        return ans')\n\n    a('')\n    a('    def __getitem__(self, key: int | str) -> typing.Any:')\n    a('        k = option_names[key] if isinstance(key, int) else key')\n    a('        try:')\n    a('            return getattr(self, k)')\n    a('        except AttributeError:')\n    a('            pass')\n    a('        raise KeyError(f\"No option named: {k}\")')\n\n    if defn.has_color_table:\n        a('')\n        a('    def __getattr__(self, key: str) -> typing.Any:')\n        a('        if key.startswith(\"color\"):')\n        a('            q = key[5:]')\n        a('            if q.isdigit():')\n        a('                k = int(q)')\n        a('                if 0 <= k <= 255:')\n        a('                    x = self.color_table[k]')\n        a(f'                    if x == 0x{NULL_COLOR_VALUE:x}:')\n        a('                        return None')\n        a('                    return Color((x >> 16) & 255, (x >> 8) & 255, x & 255)')\n        a('        raise AttributeError(key)')\n        a('')\n        a('    def __setattr__(self, key: str, val: typing.Any) -> typing.Any:')\n        a('        if key.startswith(\"color\"):')\n        a('            q = key[5:]')","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kitty/conf/generate.py#L252-L288","documentation":"Generated options classes (__getitem__) raise KeyError('No option named: {k}') when looking up an option name that the parsed configuration does not define. This code lives in the generated conf class emitted by generate_class.","triggerScenarios":"options['nonexistent_option'] or options[bad_index] on a parsed Options object where getattr raises AttributeError and the name is not in option_names.","commonSituations":"Typos in option names in scripts using the options mapping API, or accessing options that were removed/renamed between kitty versions.","solutions":["Check the exact option name in kitty's options docs","Use option_names / as_dict() to list valid keys","Pin or upgrade versions consistently between generating and consuming code"],"exampleFix":"# before\nval = opts['font_sz']\n# after\nval = opts['font_size']","handlingStrategy":"validation","validationCode":"from kitty.conf.utils import *  # generated class dependent\nvalid = set(opts.option_names) if hasattr(opts, 'option_names') else set(opts.as_dict())\nif key not in valid:\n    raise KeyError(f'{key} not valid; valid: {sorted(valid)[:10]}...')","typeGuard":"def has_option(opts, name: str) -> bool:\n    try:\n        opts[name]\n        return True\n    except KeyError:\n        return False","tryCatchPattern":"try:\n    val = opts[key]\nexcept KeyError as e:\n    if 'No option named' in str(e):\n        val = default_for(key)\n    else:\n        raise","preventionTips":["Derive option names from opts.as_dict() or option_names dynamically","Pin kitty versions when scripts depend on specific option names"],"tags":["kitty","config","options","keyerror"],"backgroundTag":"unknown-config-key","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}