{"record":{"id":"1ae1b10596d34584","repo":"aio-libs/aiohttp","slug":"keepalive-timeout-cannot-be-set-if-force-close-is","errorCode":null,"errorMessage":"keepalive_timeout cannot be set if force_close is True","messagePattern":"keepalive_timeout cannot be set if force_close is True","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/connector.py","lineNumber":339,"sourceCode":"\n    # abort transport after 2 seconds (cleanup broken connections)\n    _cleanup_closed_period = 2.0\n\n    allowed_protocol_schema_set = HIGH_LEVEL_SCHEMA_SET\n\n    def __init__(\n        self,\n        *,\n        keepalive_timeout: _SENTINEL | None | float = sentinel,\n        force_close: bool = False,\n        limit: int = 100,\n        limit_per_host: int = 0,\n        enable_cleanup_closed: bool = False,\n        timeout_ceil_threshold: float = 5,\n    ) -> None:\n        if force_close:\n            if keepalive_timeout is not None and keepalive_timeout is not sentinel:\n                raise ValueError(\n                    \"keepalive_timeout cannot be set if force_close is True\"\n                )\n        else:\n            if keepalive_timeout is sentinel:\n                keepalive_timeout = 15.0\n\n        self._timeout_ceil_threshold = timeout_ceil_threshold\n\n        loop = asyncio.get_running_loop()\n\n        self._closed = False\n        if loop.get_debug():\n            self._source_traceback = traceback.extract_stack(sys._getframe(1))\n\n        # Connection pool of reusable connections.\n        # We use a deque to store connections because it has O(1) popleft()\n        # and O(1) append() operations to implement a FIFO queue.\n        self._conns: defaultdict[","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/connector.py#L321-L357","documentation":"Raised by BaseConnector.__init__ when force_close=True is combined with an explicit keepalive_timeout (anything other than None or sentinel). force_close means connections are discarded after each request, so a keep-alive timeout is meaningless and almost always indicates a configuration mistake. The constructor rejects the contradiction up front instead of silently ignoring one of the values.","triggerScenarios":"TCPConnector(force_close=True, keepalive_timeout=30); copying values from a shared config dict that sets both; toggling force_close at runtime without clearing the timeout; misreading docs and assuming the timeout governs something else.","commonSituations":"Reusing a connector-config helper across services where one needs force_close and another needs keepalive; CI config copied from a template that hard-codes both; refactoring that left a stale field.","solutions":["If you truly want force_close (no pooling), drop keepalive_timeout entirely.","If you want pooling with a custom lifetime, set force_close=False (default) and keep keepalive_timeout.","Centralize connector construction in one helper so the two fields cannot drift apart.","Validate the config dict before passing it to TCPConnector."],"exampleFix":"# before\nconnector = aiohttp.TCPConnector(force_close=True, keepalive_timeout=30)\n# after (pick one based on intent)\nconnector = aiohttp.TCPConnector(force_close=True)\n# or\nconnector = aiohttp.TCPConnector(force_close=False, keepalive_timeout=30)","handlingStrategy":"validation","validationCode":"def build_connector(force_close=False, keepalive_timeout=None):\n    if force_close and keepalive_timeout is not None:\n        raise ValueError('keepalive_timeout is incompatible with force_close')\n    return aiohttp.TCPConnector(force_close=force_close, keepalive_timeout=keepalive_timeout)","typeGuard":"null","tryCatchPattern":"try:\n    connector = aiohttp.TCPConnector(force_close=force_close, keepalive_timeout=ka)\nexcept ValueError as exc:\n    if 'force_close' in str(exc):\n        ka = None if force_close else ka\n        connector = aiohttp.TCPConnector(force_close=force_close, keepalive_timeout=ka)\n    else:\n        raise","preventionTips":["Centralize connector construction in one helper so force_close and keepalive_timeout stay consistent.","Treat force_close=True as 'no pooling at all' and leave keepalive_timeout unset.","Add a config validator in front of user-supplied connector settings."],"tags":["connector","configuration","value-error","tcp-connector"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}