{"record":{"id":"57e2b813e4597170","repo":"pika/pika","slug":"name-must-be-callable-but-got-callback-r","errorCode":null,"errorMessage":"{name} must be callable, but got {callback!r}","messagePattern":"(.+?) must be callable, but got (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pika/adapters/utils/io_services_utils.py","lineNumber":56,"sourceCode":"    errno.EWOULDBLOCK,\n)\n\n_LOGGER = logging.getLogger(__name__)\n\n# Decorator that logs exceptions escaping from the decorated function\n_log_exceptions = pika.diagnostic_utils.create_log_exception_decorator(_LOGGER)\n\n\ndef check_callback_arg(callback: Any, name: str) -> None:\n    \"\"\"\n    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):","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/pika/pika/blob/34a407b24f08f2307578ceff870b6d7a12e7fdca/pika/adapters/utils/io_services_utils.py#L38-L74","documentation":"Pika's I/O services require a genuinely callable object (function, lambda, or instance with __call__) for asynchronous completion callbacks. check_callback_arg() rejects anything non-callable, including None, strings, ints, and plain objects. The {name} placeholder identifies which parameter was wrong (e.g. on_done, protocol_factory).","triggerScenarios":"Passing None, a string, or a non-callable object to connect_socket(), create_streaming_connection(), or the _AsyncSocketConnector/_AsyncStreamConnector constructors as the on_done / protocol_factory argument.","commonSituations":"Forgetting the on_done argument and defaulting to None; passing a method name as a string instead of the bound method; passing the return value of a call instead of the function reference.","solutions":["Pass an actual function, lambda, or bound-method reference (not its return value)","Confirm the arg is required - these I/O-service callbacks do not accept None; do not omit them","If you meant 'no callback', that path is not supported here; restructure to always supply one"],"exampleFix":"# before\nnbio.connect_socket(sock, addr, on_done=None)  # TypeError\n\n# after\ndef _on_done(error):\n    ...\nnbio.connect_socket(sock, addr, on_done=_on_done)","handlingStrategy":"type-guard","validationCode":"def _ensure_callback(cb, name):\n    if not callable(cb):\n        raise TypeError(f'{name} must be callable, got {cb!r}')\n    return cb\n\nnbio.connect_socket(sock, addr, on_done=_ensure_callback(my_cb, 'on_done'))","typeGuard":"def is_callback(value) -> bool:\n    return callable(value)","tryCatchPattern":"try:\n    nbio.connect_socket(sock, addr, on_done=cb)\nexcept TypeError as e:\n    if 'must be callable' in str(e):\n        raise  # or supply a real callback\n    raise","preventionTips":["Pass function/lambda/bound-method references, never their return values or strings","These I/O-service callbacks are mandatory - never pass None where a callback is required","Add a callable() assert in your own wrapper before delegating to pika"],"tags":["callback","typing","io","adapter-internals"],"backgroundTag":null,"analyzedSha":"34a407b24f08f2307578ceff870b6d7a12e7fdca","analyzedAt":"2026-08-07T23:58:35.009Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}