kovidgoyal/kitty · error · KeyError

No option named: {k}

Error message

No option named: {k}

What it means

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>'.

Source

Thrown at kitty/options/types.py:839

    def _asdict(self) -> dict[str, typing.Any]:
        return {k: self._copy_of_val(k) for k in self}

    def _replace(self, **kw: typing.Any) -> "Options":
        ans = Options()
        for name in self:
            setattr(ans, name, self._copy_of_val(name))
        for name, val in kw.items():
            setattr(ans, name, val)
        return ans

    def __getitem__(self, key: int | str) -> typing.Any:
        k = option_names[key] if isinstance(key, int) else key
        try:
            return getattr(self, k)
        except AttributeError:
            pass
        raise KeyError(f"No option named: {k}")

    def __getattr__(self, key: str) -> typing.Any:
        if key.startswith("color"):
            q = key[5:]
            if q.isdigit():
                k = int(q)
                if 0 <= k <= 255:
                    x = self.color_table[k]
                    if x == 0xffffffff:
                        return None
                    return Color((x >> 16) & 255, (x >> 8) & 255, x & 255)
        raise AttributeError(key)

    def __setattr__(self, key: str, val: typing.Any) -> typing.Any:
        if key.startswith("color"):
            q = key[5:]
            if q.isdigit():
                k = int(q)

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Check the exact option name against kitty/options/types.py or `kitty +runpy` introspection
  2. Guard access with `if hasattr(opts, name)` or use opts.get-style patterns
  3. If version-dependent, gate the access on the kitty version or feature detection

Example fix

# before
val = opts['allow_hyperlinks']  # AttributeError->KeyError if absent
# after
val = getattr(opts, 'allow_hyperlinks', None)
Defensive patterns

Strategy: try-catch

Validate before calling

from kitty.options.types import Options
name = 'some_option'
if not hasattr(opts, name) and not (name.startswith('color') and name[5:].isdigit()):
    print(f'unknown option: {name}')

Type guard

def option_exists(opts, name: str) -> bool:
    try:
        _ = opts[name]
        return True
    except KeyError:
        return False

Try / catch

try:
    val = opts[name]
except KeyError:
    val = default  # or skip feature

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27). Data as JSON: /api/errors/2f2e5b706de756fa. Report an issue: GitHub.