{"record":{"id":"8fa5c8da9eb87b51","repo":"pika/pika","slug":"paramter-must-be-a-file-descriptor-but-got-fd-r","errorCode":null,"errorMessage":"Paramter must be a file descriptor, but got {fd!r}","messagePattern":"Paramter must be a file descriptor, but got (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pika/adapters/utils/io_services_utils.py","lineNumber":67,"sourceCode":"    Raise TypeError if callback is not callable.\n\n    :param callback: callback to check\n    :param name: Name to include in exception text\n    :raises TypeError:\n    \"\"\"\n    if not callable(callback):\n        raise TypeError(f'{name} must be callable, but got {callback!r}')\n\n\ndef check_fd_arg(fd: int) -> None:\n    \"\"\"\n    Raise TypeError if file descriptor is not an integer.\n\n    :param fd: file descriptor\n    :raises TypeError:\n    \"\"\"\n    if not isinstance(fd, numbers.Integral):\n        raise TypeError(f'Paramter must be a file descriptor, but got {fd!r}')\n\n\ndef _retry_on_sigint(func):\n    \"\"\"Function decorator for retrying on SIGINT.\"\"\"\n\n    @functools.wraps(func)\n    def retry_sigint_wrap(*args, **kwargs):\n        \"\"\"Wrapper for decorated function.\"\"\"\n        while True:\n            try:\n                return func(*args, **kwargs)\n            except pika._utils.SOCKET_ERROR as error:\n                if error.errno == errno.EINTR:\n                    continue\n                raise\n\n    return retry_sigint_wrap\n","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/pika/pika/blob/34a407b24f08f2307578ceff870b6d7a12e7fdca/pika/adapters/utils/io_services_utils.py#L49-L85","documentation":"I/O services that watch file descriptors (add_reader/add_writer/remove_*) require an integer file descriptor. check_fd_arg() uses numbers.Integral, so floats, strings, socket objects, and None are rejected with TypeError. Note the source typo 'Paramter' is pre-existing; match it if grepping logs.","triggerScenarios":"Passing a socket object instead of sock.fileno(); passing a float fd; passing a stringified fd. Happens when calling low-level nbio file-descriptor registration methods directly (typically from a custom adapter).","commonSituations":"Confusing a socket object with its integer fd; calling private nbio APIs from bespoke adapter code; off-by-one producing a float.","solutions":["Call sock.fileno() to obtain the integer descriptor before passing it","Ensure you pass an int, not a socket object or float","Use pika's public connection APIs which handle fd extraction internally"],"exampleFix":"# before\nnbio.add_reader(my_socket, callback)  # TypeError\n\n# after\nnbio.add_reader(my_socket.fileno(), callback)","handlingStrategy":"type-guard","validationCode":"import numbers\ndef as_fd(value) -> int:\n    if not isinstance(value, numbers.Integral):\n        raise TypeError(f'Expected int fd, got {value!r}')\n    return int(value)\n\nnbio.add_reader(as_fd(sock.fileno()), cb)","typeGuard":"import numbers\ndef is_file_descriptor(value) -> bool:\n    return isinstance(value, numbers.Integral)","tryCatchPattern":"try:\n    nbio.add_reader(fd, cb)\nexcept TypeError as e:\n    if 'file descriptor' in str(e):\n        nbio.add_reader(sock.fileno(), cb)\n    else:\n        raise","preventionTips":["Always call sock.fileno() to extract the integer descriptor","Keep socket objects and their fds distinct in your variable naming","Avoid calling private nbio registration APIs directly unless writing an adapter"],"tags":["socket","file-descriptor","io","typing","adapter-internals"],"backgroundTag":null,"analyzedSha":"34a407b24f08f2307578ceff870b6d7a12e7fdca","analyzedAt":"2026-08-07T23:58:35.009Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}