kovidgoyal/kitty · error · ValueError

Invalid listen-on value: {spec} must be of the form protocol

Error message

Invalid listen-on value: {spec} must be of the form protocol:address

What it means

parse_address_spec() requires a listen-on string of the form 'protocol:address'; when the spec contains no ':' at all, spec.split(':', 1) raises ValueError, which is re-raised with this clearer message. Valid protocols are 'unix:' and 'tcp:'.

Source

Thrown at kitty/utils.py:391

    for loc in candidates:
        if os.access(loc, os.W_OK | os.R_OK | os.X_OK):
            yield loc


def unix_socket_paths(name: str, ext: str = '.lock') -> Generator[str, None, None]:
    home = os.path.expanduser('~')
    for loc in unix_socket_directories():
        filename = ('.' if loc == home else '') + name + ext
        yield os.path.join(loc, filename)


def parse_address_spec(spec: str) -> tuple[AddressFamily, tuple[str, int] | str, str | None]:
    import socket

    try:
        protocol, rest = spec.split(':', 1)
    except ValueError:
        raise ValueError(f'Invalid listen-on value: {spec} must be of the form protocol:address')
    socket_path = None
    address: str | tuple[str, int] = ''
    if protocol == 'unix':
        family = socket.AF_UNIX
        address = rest
        if address.startswith('@') and len(address) > 1:
            address = '\0' + address[1:]
        else:
            socket_path = address
    elif protocol in ('tcp', 'tcp6'):
        family = socket.AF_INET if protocol == 'tcp' else socket.AF_INET6
        if rest.startswith('['):  # ]
            host = rest[1:]
            host, sep, leftover = host.rpartition(']')
            _, port = leftover.rsplit(':', 1)
            if ':' in host and protocol == 'tcp':
                family = socket.AF_INET6
        else:

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Use unix:/path/to/socket or tcp:host:port (e.g. tcp:localhost:9901)
  2. Validate the spec contains a colon before passing it
  3. If generating kitty.conf programmatically, assert the format in your generator

Example fix

# before
kitty --listen-on=/tmp/kitty-sock
# after
kitty --listen-on=unix:/tmp/kitty-sock
Defensive patterns

Strategy: validation

Validate before calling

def valid_address_spec(spec: str) -> bool:
    return ':' in spec

Try / catch

try:
    fam, addr, path = parse_address_spec(spec)
except ValueError as e:
    if 'Invalid listen-on value' in str(e):
        spec = f'unix:{default_socket}'
        fam, addr, path = parse_address_spec(spec)
    else:
        raise

Prevention

When it happens

Trigger: --listen-on=9901 (bare port), --listen-on=localhost (no protocol), or any spec without a colon.

Common situations: Mistaking kitty's syntax for other tools' listen formats (e.g. 'host:port' without 'tcp:'); typos in kitty.conf's listen_on directive; script-generated configs dropping the protocol prefix.

Related errors


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