{"record":{"id":"6e6238be5daa411e","repo":"kovidgoyal/kitty","slug":"size-must-be-a-non-negative-integer","errorCode":null,"errorMessage":"'size' must be a non-negative integer","messagePattern":"'size' must be a non-negative integer","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"kitty/shm.py","lineNumber":63,"sourceCode":"    _mmap: mmap.mmap | None = None\n    _size: int = 0\n    size_fmt = '!I'\n    num_bytes_for_size = struct.calcsize(size_fmt)\n\n    def __init__(\n        self,\n        name: str = '',\n        size: int = 0,\n        readonly: bool = False,\n        mode: int = stat.S_IREAD | stat.S_IWRITE,\n        prefix: str = 'kitty-',\n        unlink_on_exit: bool = False,\n        ignore_close_failure: bool = False,\n    ):\n        self.unlink_on_exit = unlink_on_exit\n        self.ignore_close_failure = ignore_close_failure\n        if size < 0:\n            raise TypeError(\"'size' must be a non-negative integer\")\n        if size and name:\n            raise TypeError('Cannot specify both name and size')\n        if not name:\n            flags = os.O_CREAT | os.O_EXCL\n            if not size:\n                raise TypeError(\"'size' must be > 0\")\n        else:\n            flags = 0\n        flags |= os.O_RDONLY if readonly else os.O_RDWR\n\n        tries = 30\n        while not name and tries > 0:\n            tries -= 1\n            q = make_filename(prefix)\n            try:\n                self._fd = shm_open(q, flags, mode)\n                name = q\n            except FileExistsError:","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kitty/shm.py#L45-L81","documentation":"SharedMemory.__init__ validates its arguments: a negative size is rejected immediately with TypeError(\"'size' must be a non-negative integer\"). A zero size is also rejected later ('size' must be > 0) unless an existing name is given, since a new mapping must have nonzero size.","triggerScenarios":"Calling SharedMemory(size=-1) (negative size), or SharedMemory(size=0) without name (new object must have positive size); commonly from passing an unvalidated or computed size that can be 0/negative, e.g. len(data) with empty data.","commonSituations":"Allocating shm sized from user input or empty payloads; refactoring code where size defaults to 0 and previously a name was always passed.","solutions":["Ensure size is a positive int before constructing: guard `size = max(0, len(payload))` and skip/short-circuit when 0","Pass name= only when attaching to an existing shm, never together with a positive size","Validate with isinstance(size, int) and size > 0 at the API boundary"],"exampleFix":"# before\nshm = SharedMemory(size=len(payload))  # payload may be empty\n# after\nif not payload:\n    return\nshm = SharedMemory(size=len(payload))","handlingStrategy":"type-guard","validationCode":"def valid_shm_size(size: object) -> bool:\n    return isinstance(size, int) and not isinstance(size, bool) and size > 0","typeGuard":"def is_valid_shm_size(size: unknown) -> size is int:\n    return isinstance(size, int) and not isinstance(size, bool) and size > 0","tryCatchPattern":"try:\n    shm = SharedMemory(size=size)\nexcept TypeError as e:\n    raise ValueError(f'bad SharedMemory size: {size!r}') from e","preventionTips":["Short-circuit on empty payloads instead of allocating 0-size shm","Validate size > 0 at API boundaries","Never pass both name and a positive size"],"tags":["kitty","shared-memory","argument-validation","typeerror"],"backgroundTag":"invalid-argument-value","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}