kovidgoyal/kitty · error · AttributeError
{name} is not a valid color
Error message
{name} is not a valid color What it means
Raised by __getattr__ in kitty's window title bar color formatter when a color-like attribute name passed to the SGR color formatter cannot be parsed by to_color(). The class synthesizes ANSI escape sequences from attribute names like 'red', '#ff00ff' (via '_ff00ff'), or 'indexed:N', and any name that isn't a recognized color spec raises AttributeError. It is an AttributeError rather than ValueError because it occurs during dynamic attribute access.
Source
Thrown at kitty/window_title_bar.py:67
elif q == 'window':
opts = get_options()
if self.is_active:
fg_color = _resolve_color(opts.window_title_bar_active_foreground, opts.active_tab_foreground)
bg_color = _resolve_color(opts.window_title_bar_active_background, opts.active_tab_background)
col = color_from_int(color_as_int(fg_color if self.which == '3' else bg_color))
else:
fg_color = _resolve_color(opts.window_title_bar_inactive_foreground, opts.inactive_tab_foreground)
bg_color = _resolve_color(opts.window_title_bar_inactive_background, opts.inactive_tab_background)
col = color_from_int(color_as_int(fg_color if self.which == '3' else bg_color))
ans = f'8{color_as_sgr(col)}'
elif q.startswith('color'):
ans = f'8:5:{int(q[5:])}'
else:
if name.startswith('_'):
q = f'#{name[1:]}'
c = to_color(q)
if c is None:
raise AttributeError(f'{name} is not a valid color')
ans = f'8{color_as_sgr(c)}'
return f'\x1b[{self.which}{ans}m'
class WindowTitleFormatter:
reset = '\x1b[0m'
fg = WindowTitleColorFormatter('3')
bg = WindowTitleColorFormatter('4')
bold = '\x1b[1m'
nobold = '\x1b[22m'
italic = '\x1b[3m'
noitalic = '\x1b[23m'
class WindowTitleData(NamedTuple):
title: str
is_active: bool
window_id: intView on GitHub (pinned to 6d5d0c4406)
Solutions
- Correct the color name to one kitty's to_color() accepts: standard color names, #RRGGBB (accessed as _RRGGBB), or indexed:N / 8:5:N specs
- Validate color strings with kitty.rgb.to_color() before using them as attribute names
- If the attribute isn't meant to be a color, rename it so it doesn't collide with __getattr__-based color lookup
Example fix
// before sgr = formatter.my_colr # typo -> AttributeError: my_colr is not a valid color # after sgr = formatter._ff0000 # explicit hex red, or a name to_color() accepts
Defensive patterns
Strategy: validation
Validate before calling
from kitty.rgb import to_color
def valid_color(name: str) -> bool:
q = f'#{name[1:]}' if name.startswith('_') else name
return to_color(q) is not None Type guard
def is_valid_color_name(name: str) -> bool:
from kitty.rgb import to_color
q = f'#{name[1:]}' if name.startswith('_') else name
return to_color(q) is not None Try / catch
try:
sgr = getattr(formatter, name)
except AttributeError as e:
if 'is not a valid color' in str(e):
sgr = '' # skip or use default color
else:
raise Prevention
- Validate color strings with kitty.rgb.to_color() before turning them into attribute lookups
- Keep user-configurable color names in a curated allowlist
- Lint theme configs for color names at load time
When it happens
Trigger: Accessing a color attribute on the title-bar formatter object with an invalid name, e.g. formatter.notacolor, formatter._zzzzzz (malformed hex), or an indexed color spec that doesn't parse; any name where to_color(q) returns None.
Common situations: Typos in theme/config color names, using CSS color names kitty doesn't support, malformed hex like '_ff00f' (5 digits), or passing a variable that is None/empty so the attribute name becomes garbage.
Related errors
- Unknown marker type: {ftype}
- {rest} is not a valid marker specification
- {rest} is not a valid scroll_to_mark destination
- ENOSYS
- timed out waiting for response from terminal
AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27).
Data as JSON: /api/errors/addc6607d4aac355.
Report an issue: GitHub.