{"id":"866cff0b279d0bd1","repo":"redis/redis-py","slug":"max-connections-must-be-a-positive-integer","errorCode":null,"errorMessage":"\"max_connections\" must be a positive integer","messagePattern":"\"max_connections\" must be a positive integer","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"redis/asyncio/connection.py","lineNumber":2627,"sourceCode":"        ``ValueError`` to be raised. Once parsed, the querystring arguments\n        and keyword arguments are passed to the ``ConnectionPool``'s\n        class initializer. In the case of conflicting arguments, querystring\n        arguments always win.\n        \"\"\"\n        url_options = parse_url(url)\n        kwargs.update(url_options)\n        return cls(**kwargs)\n\n    def __init__(\n        self,\n        connection_class: Type[AbstractConnection] = Connection,\n        max_connections: Optional[int] = None,\n        maint_notifications_config: MaintNotificationsConfig | None = None,\n        **connection_kwargs,\n    ):\n        max_connections = max_connections or 100\n        if not isinstance(max_connections, int) or max_connections < 0:\n            raise ValueError('\"max_connections\" must be a positive integer')\n\n        self.connection_class = connection_class\n        self._connection_kwargs = connection_kwargs\n        self.max_connections = max_connections\n\n        # Resolve the HIMPORT registry. A pre-built ``himport_registry`` (shared, e.g.\n        # from the cluster client) takes precedence; otherwise build a fresh empty one.\n        # A registry always exists so runtime ``himport_prepare`` mutates a single object\n        # every connection already shares. The object stays in ``connection_kwargs`` so\n        # it reaches every connection. It is injected unconditionally (like other\n        # auto-added pool kwargs), so a custom ``connection_class`` must accept\n        # ``**kwargs`` (or a ``himport_registry`` parameter), as built-ins do.\n        himport_registry = connection_kwargs.get(\"himport_registry\")\n        if himport_registry is None:\n            himport_registry = HImportRegistry()\n            connection_kwargs[\"himport_registry\"] = himport_registry\n        self.himport_registry = himport_registry\n","sourceCodeStart":2609,"sourceCodeEnd":2645,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/asyncio/connection.py#L2609-L2645","documentation":"Raised by ConnectionPool.__init__ when max_connections is not an int or is negative. Note the guard checks isinstance int and < 0 (0 is allowed because the line above coerces falsy values to 100). A non-integer (e.g., a string from a URL/env var) or a negative number fails the check. The default when None/0/falsy is 100.","triggerScenarios":"Passing max_connections as a non-int (string '50', float 50.0, or None-coerced-but-still-wrong value) or a negative int to ConnectionPool, Redis(connection_pool=...) or via a URL with max_connections in the query string that parses to a string. The check at connection.py:2626 runs before the pool is usable.","commonSituations":"Reading max_connections from an environment variable or config file as a string and passing it unconverted; passing a float; off-by-one or sign errors computing pool size; URL parsing where the value is a str until coerced elsewhere.","solutions":["Coerce max_connections to int explicitly before passing it: int(os.environ['MAX_CONN']).","Ensure the value is a positive integer (>= 0; 0/None becomes the default 100).","Validate the value at the boundary where you read configuration, not at pool construction."],"exampleFix":"// before\npool = ConnectionPool(max_connections=os.environ['REDIS_MAX_CONN'])\n// after\npool = ConnectionPool(max_connections=int(os.environ['REDIS_MAX_CONN']))","handlingStrategy":"type-guard","validationCode":"def coerce_max_connections(v):\n    v = int(v)\n    if v < 0:\n        raise ValueError('max_connections must be >= 0')\n    return v or 100\n\npool = ConnectionPool(max_connections=coerce_max_connections(os.environ.get('REDIS_MAX_CONN', 100)))","typeGuard":"def is_valid_max_connections(v) -> bool:\n    return isinstance(v, int) and not isinstance(v, bool) and v >= 0","tryCatchPattern":"try:\n    pool = ConnectionPool(max_connections=raw)\nexcept ValueError as e:\n    if 'max_connections' in str(e):\n        raw = int(raw); pool = ConnectionPool(max_connections=raw)\\n    else:\\n        raise","preventionTips":["Coerce config-sourced max_connections to int at the config boundary.","Reject bool (isinstance(True, int) is True) explicitly if relevant.","Validate >= 0 before construction."],"tags":["configuration","pool","validation","asyncio"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}