{"record":{"id":"797f1f96818e4cc1","repo":"python/cpython","slug":"callable-must-be-used-as-callable-arg-resu","errorCode":null,"errorMessage":"Callable must be used as Callable[[arg, ...], result].","messagePattern":"Callable must be used as Callable\\[\\[arg, \\.\\.\\.\\], result\\]\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/_collections_abc.py","lineNumber":473,"sourceCode":"            return _check_methods(C, \"__buffer__\")\n        return NotImplemented\n\n\nclass _CallableGenericAlias(GenericAlias):\n    \"\"\" Represent `Callable[argtypes, resulttype]`.\n\n    This sets ``__args__`` to a tuple containing the flattened\n    ``argtypes`` followed by ``resulttype``.\n\n    Example: ``Callable[[int, str], float]`` sets ``__args__`` to\n    ``(int, str, float)``.\n    \"\"\"\n\n    __slots__ = ()\n\n    def __new__(cls, origin, args):\n        if not (isinstance(args, tuple) and len(args) == 2):\n            raise TypeError(\n                \"Callable must be used as Callable[[arg, ...], result].\")\n        t_args, t_result = args\n        if isinstance(t_args, (tuple, list)):\n            args = (*t_args, t_result)\n        elif not _is_param_expr(t_args):\n            raise TypeError(f\"Expected a list of types, an ellipsis, \"\n                            f\"ParamSpec, or Concatenate. Got {t_args}\")\n        return super().__new__(cls, origin, args)\n\n    def __repr__(self):\n        if len(self.__args__) == 2 and _is_param_expr(self.__args__[0]):\n            return super().__repr__()\n        from annotationlib import type_repr\n        return (f'collections.abc.Callable'\n                f'[[{\", \".join([type_repr(a) for a in self.__args__[:-1]])}], '\n                f'{type_repr(self.__args__[-1])}]')\n\n    def __reduce__(self):","sourceCodeStart":455,"sourceCodeEnd":491,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_collections_abc.py#L455-L491","documentation":"TypeError raised by collections.abc.CallableType.__new__ (Lib/_collections_abc.py, reached via typing.Callable) when the subscription does not have the two-part shape Callable[[arg, ...], result]. Callable's parameter list must be exactly a 2-tuple: a list of argument types (or ...) followed by the return type, so any other arity or non-tuple argument is rejected.","triggerScenarios":"Writing typing.Callable[[int, str]] (missing the result type), typing.Callable[int, str, None] (three entries), or constructing typing.Callable[...] with a single argument. Building Callable args programmatically with the wrong tuple length hits the same check.","commonSituations":"Typing beginners omitting the return type; metaprogramming that slices/concatenates __args__ and re-subscribes Callable; copy-paste edits that delete the second element; runtime type inspection code that reconstructs generic aliases.","solutions":["Always subscribe with two slots: Callable[[int, str], bool] or Callable[..., None].","When constructing programmatically, build args as (list_of_params, result) before subscripting.","Check existing __args__/__parameters__ with typing.get_type_hints or typing.get_args instead of re-assembling aliases by hand.","For parameterized variants use ParamSpec/Concatenate (e.g. Callable[Concatenate[int, P], R]) which still occupy exactly two slots."],"exampleFix":"# before\nHandler = typing.Callable[[str, bytes]]      # TypeError\nRun = typing.Callable[int, str, None]        # TypeError\n\n# after\nHandler = typing.Callable[[str, bytes], None]\nRun = typing.Callable[[int, str], None]","handlingStrategy":"validation","validationCode":"def callable_args_ok(args) -> bool:\n    return isinstance(args, tuple) and len(args) == 2\n\n# before dynamic construction:\nassert callable_args_ok(params_and_result), f'bad Callable args: {params_and_result!r}'","typeGuard":"import typing\n\ndef is_valid_callable_alias(tp) -> bool:\n    origin = typing.get_origin(tp)\n    return origin is not None and len(typing.get_args(tp)) in (2,) or (\n        origin is collections.abc.Callable and len(tp.__args__) >= 2\n    )","tryCatchPattern":"try:\n    Alias = typing.Callable[params, result]\nexcept TypeError as e:\n    if 'Callable must be used as' in str(e):\n        raise TypeError(f'fix Callable shape in config: {params!r}') from e\n    raise","preventionTips":["Mentor rule: Callable always takes exactly two slots — [params], result.","Let type checkers (mypy/pyright) catch malformed aliases at lint time.","For generated annotations, assert the two-tuple shape in tests."],"tags":["typing","collections-abc","type-hints","developer-error"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}