{"record":{"id":"be7891bb63d95ccb","repo":"kovidgoyal/kitty","slug":"enametoolong","errorCode":"ENAMETOOLONG","errorMessage":"SHM filename prefix {prefix} is too long","messagePattern":"SHM filename prefix (.+?) is too long","errorType":"error_code","errorClass":"OSError","httpStatus":null,"severity":"error","filePath":"kitty/shm.py","lineNumber":29,"sourceCode":"import secrets\nimport stat\nimport struct\nfrom typing import Literal, cast\n\nfrom kitty.fast_data_types import SHM_NAME_MAX, shm_open, shm_unlink\n\n\ndef make_filename(prefix: str) -> str:\n    \"Create a random filename for the shared memory object.\"\n    # number of random bytes to use for name. Use a largeish value\n    # to make double unlink safe.\n    if not prefix.startswith('/'):\n        # FreeBSD requires name to start with /\n        prefix = '/' + prefix\n    plen = len(prefix.encode('utf-8'))\n    safe_length = min(plen + 64, SHM_NAME_MAX)\n    if safe_length - plen < 2:\n        raise OSError(errno.ENAMETOOLONG, f'SHM filename prefix {prefix} is too long')\n    nbytes = (safe_length - plen) // 2\n    name = prefix + secrets.token_hex(nbytes)\n    return name\n\n\nclass SharedMemory:\n    \"\"\"\n    Create or access randomly named shared memory. To create call with empty name and specific size.\n    To access call with name only.\n\n    WARNING: The actual size of the shared memory may be larger than the requested size.\n    \"\"\"\n\n    _fd: int = -1\n    _name: str = ''\n    _mmap: mmap.mmap | None = None\n    _size: int = 0\n    size_fmt = '!I'","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kitty/shm.py#L11-L47","documentation":"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.","triggerScenarios":"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__.","commonSituations":"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.","solutions":["Shorten the prefix — use a short fixed tag plus a hash of the long identifier: e.g. '/kt-' + sha1(key).hexdigest()[:16]","Keep the prefix well under ~30 bytes for cross-platform safety","Catch OSError with errno.ENAMETOOLONG and retry with a truncated/hashed prefix"],"exampleFix":"# before\nshm = SharedMemory(name_prefix='/kitty-cache-' + very_long_key)\n# after\nimport hashlib\nshm = SharedMemory(name_prefix='/kt-' + hashlib.sha1(very_long_key.encode()).hexdigest()[:16])","handlingStrategy":"validation","validationCode":"SHM_NAME_MAX_SAFE = 64  # conservative cross-platform budget\n\ndef prefix_ok(prefix: str, max_len: int = 255, min_room: int = 2) -> bool:\n    plen = len(('/' + prefix if not prefix.startswith('/') else prefix).encode())\n    return min(plen + 64, max_len) - plen >= min_room","typeGuard":null,"tryCatchPattern":"import errno\ntry:\n    shm = SharedMemory(name_prefix=prefix)\nexcept OSError as e:\n    if e.errno == errno.ENAMETOOLONG:\n        import hashlib\n        shm = SharedMemory(name_prefix='/kt-' + hashlib.sha1(prefix.encode()).hexdigest()[:16])\n    else:\n        raise","preventionTips":["Use short hashed prefixes for shm names","Stay under ~30 bytes of prefix for portability","Handle ENAMETOOLONG explicitly with a retry using a shorter name"],"tags":["kitty","shared-memory","filename-too-long","posix"],"backgroundTag":"filename-too-long","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}