{"record":{"id":"92a6113ea023e31c","repo":"aio-libs/aiohttp","slug":"timeout-parameter-cannot-be-of-type-timeout-typ","errorCode":null,"errorMessage":"timeout parameter cannot be of {type(timeout)} type, please use 'timeout=ClientTimeout(...)'","messagePattern":"timeout parameter cannot be of (.+?) type, please use 'timeout=ClientTimeout\\(\\.\\.\\.\\)'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/client.py","lineNumber":350,"sourceCode":"        else:\n            self._base_url = URL(base_url)\n            self._base_url_origin = self._base_url.origin()\n            assert self._base_url.absolute, \"Only absolute URLs are supported\"\n        if self._base_url is not None and not self._base_url.path.endswith(\"/\"):\n            raise ValueError(\"base_url must have a trailing '/'\")\n\n        if not isinstance(ssl, SSL_ALLOWED_TYPES):\n            raise TypeError(\n                \"ssl should be SSLContext, Fingerprint, or bool, \"\n                f\"got {ssl!r} instead.\"\n            )\n\n        loop = asyncio.get_running_loop()\n\n        if timeout is sentinel or timeout is None:\n            timeout = ClientTimeout()\n        if not isinstance(timeout, ClientTimeout):\n            raise ValueError(\n                f\"timeout parameter cannot be of {type(timeout)} type, \"\n                \"please use 'timeout=ClientTimeout(...)'\",\n            )\n        self._timeout = timeout\n\n        if ssl_shutdown_timeout is not sentinel:\n            warnings.warn(\n                \"The ssl_shutdown_timeout parameter is deprecated and will be removed in aiohttp 4.0\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n\n        if connector is None:\n            connector = TCPConnector(ssl_shutdown_timeout=ssl_shutdown_timeout)\n        # Initialize these three attrs before raising any exception,\n        # they are used in __del__\n        self._connector = connector\n        self._loop = loop","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d9aaf697c2cd4783ca5749a971965c689f3ec24f/aiohttp/client.py#L332-L368","documentation":"Raised as a ValueError in ClientSession.__init__ (client.py:349-353) when the timeout argument is neither the sentinel, None, nor a ClientTimeout instance. aiohttp requires all per-session and per-request timeouts to be expressed as a ClientTimeout dataclass so connect/read/total/sock_connect/sock_read can be configured independently. Passing a bare float/int (the pre-3.x style) is rejected because there is no way to know which timeout dimension it should clamp.","triggerScenarios":"Constructing ClientSession(timeout=30) or session.get(url, timeout=10) with a numeric value instead of ClientTimeout(total=30). Also passing timeout=0 or a string, a timedelta, or any non-ClientTimeout object. Note: timeout=None is explicitly accepted (client.py:347) and means 'use the default ClientTimeout()', so None does not trigger this.","commonSituations":"Migrating from aiohttp 2.x or the requests library where timeout=float is idiomatic. Copying examples from outdated tutorials. Wrapping the timeout in a variable that conditionally becomes a number. Confusing the ws_connect timeout (which historically accepted a float and still emits a DeprecationWarning) with the request/session timeout.","solutions":["Replace any numeric timeout with timeout=ClientTimeout(total=<seconds>) (or set sock_read=/sock_connect= for finer control).","Import ClientTimeout: from aiohttp import ClientTimeout.","Pass timeout=None (not a number) when you want aiohttp's default timeout rather than a custom one.","Audit code paths that forward timeout=**kwargs verbatim and coerce values into ClientTimeout at the boundary."],"exampleFix":"# before\nsession = aiohttp.ClientSession(timeout=30)\nawait session.get(url, timeout=10)\n\n# after\nfrom aiohttp import ClientTimeout\nsession = aiohttp.ClientSession(timeout=ClientTimeout(total=30))\nawait session.get(url, timeout=ClientTimeout(total=10))","handlingStrategy":"type-guard","validationCode":"from aiohttp import ClientTimeout\n\ndef coerce_timeout(t):\n    if t is None or isinstance(t, ClientTimeout):\n        return t\n    if isinstance(t, (int, float)):\n        return ClientTimeout(total=t)\n    raise TypeError(f'timeout must be ClientTimeout or number, got {type(t)}')","typeGuard":"from aiohttp import ClientTimeout\n\ndef is_client_timeout(v) -> bool:\n    return v is None or isinstance(v, ClientTimeout)","tryCatchPattern":"try:\n    session = aiohttp.ClientSession(timeout=my_timeout)\nexcept ValueError as e:\n    if 'timeout parameter cannot be' in str(e):\n        # fallback: build a ClientTimeout from the offending value if numeric\n        session = aiohttp.ClientSession(timeout=ClientTimeout(total=float(my_timeout)))\n    else:\n        raise","preventionTips":["Centralize timeout construction behind one helper that always returns ClientTimeout.","Never forward raw **kwargs containing timeout into aiohttp without coercion.","Statically check with mypy using aiohttp's type stubs for the timeout parameter."],"tags":["client","timeout","configuration","migration"],"analyzedSha":"d9aaf697c2cd4783ca5749a971965c689f3ec24f","analyzedAt":"2026-08-06T21:30:48.638Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}