kovidgoyal/kitty · error · OSError

ENAMETOOLONG

ENAMETOOLONG

Error message

SHM filename prefix {prefix} is too long

What it means

SharedMemory.make_filename builds a POSIX shared-memory object name from a prefix plus random hex, capped at SHM_NAME_MAX. If the prefix is so long that fewer than ~2 characters of room remain for randomness, it raises OSError(ENAMETOOLONG). The check is safe_length - plen < 2 after clamping to the max.

Source

Thrown at kitty/shm.py:29

import secrets
import stat
import struct
from typing import Literal, cast

from kitty.fast_data_types import SHM_NAME_MAX, shm_open, shm_unlink


def make_filename(prefix: str) -> str:
    "Create a random filename for the shared memory object."
    # number of random bytes to use for name. Use a largeish value
    # to make double unlink safe.
    if not prefix.startswith('/'):
        # FreeBSD requires name to start with /
        prefix = '/' + prefix
    plen = len(prefix.encode('utf-8'))
    safe_length = min(plen + 64, SHM_NAME_MAX)
    if safe_length - plen < 2:
        raise OSError(errno.ENAMETOOLONG, f'SHM filename prefix {prefix} is too long')
    nbytes = (safe_length - plen) // 2
    name = prefix + secrets.token_hex(nbytes)
    return name


class SharedMemory:
    """
    Create or access randomly named shared memory. To create call with empty name and specific size.
    To access call with name only.

    WARNING: The actual size of the shared memory may be larger than the requested size.
    """

    _fd: int = -1
    _name: str = ''
    _mmap: mmap.mmap | None = None
    _size: int = 0
    size_fmt = '!I'

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Shorten the prefix — use a short fixed tag plus a hash of the long identifier: e.g. '/kt-' + sha1(key).hexdigest()[:16]
  2. Keep the prefix well under ~30 bytes for cross-platform safety
  3. Catch OSError with errno.ENAMETOOLONG and retry with a truncated/hashed prefix

Example fix

# before
shm = SharedMemory(name_prefix='/kitty-cache-' + very_long_key)
# after
import hashlib
shm = SharedMemory(name_prefix='/kt-' + hashlib.sha1(very_long_key.encode()).hexdigest()[:16])
Defensive patterns

Strategy: validation

Validate before calling

SHM_NAME_MAX_SAFE = 64  # conservative cross-platform budget

def prefix_ok(prefix: str, max_len: int = 255, min_room: int = 2) -> bool:
    plen = len(('/' + prefix if not prefix.startswith('/') else prefix).encode())
    return min(plen + 64, max_len) - plen >= min_room

Try / catch

import errno
try:
    shm = SharedMemory(name_prefix=prefix)
except OSError as e:
    if e.errno == errno.ENAMETOOLONG:
        import hashlib
        shm = SharedMemory(name_prefix='/kt-' + hashlib.sha1(prefix.encode()).hexdigest()[:16])
    else:
        raise

Prevention

When it happens

Trigger: Calling SharedMemory(name_prefix=...) with a very long prefix such that len(prefix bytes) + 64 exceeds SHM_NAME_MAX by more than 62 bytes; i.e. prefixes approaching or exceeding the shm name limit (~31–255 bytes depending on platform). Reached via SharedMemory.__init__.

Common situations: Encoding cache keys or long identifiers into the shm prefix; portability between Linux (255) and FreeBSD/macOS (shorter shm name limits) where a prefix fine on Linux fails elsewhere.

Related errors


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