{"record":{"id":"ec53675de88cce77","repo":"redis/redis-py","slug":"protocol-must-be-an-integer-ec5367","errorCode":null,"errorMessage":"protocol must be an integer","messagePattern":"protocol must be an integer","errorType":"validation","errorClass":"ConnectionError","httpStatus":null,"severity":"error","filePath":"redis/connection.py","lineNumber":926,"sourceCode":"                self.retry.update_supported_errors(self.retry_on_error)\n        else:\n            self.retry = Retry(NoBackoff(), 0)\n        self.health_check_interval = health_check_interval\n        self.next_health_check = 0\n        self.redis_connect_func = redis_connect_func\n        self.encoder = Encoder(encoding, encoding_errors, decode_responses)\n        self.handshake_metadata = None\n        self._sock = None\n        self._socket_read_size = socket_read_size\n        self._connect_callbacks = []\n        self._buffer_cutoff = 6000\n        self._re_auth_token: Optional[TokenInterface] = None\n        try:\n            p = int(protocol)\n        except TypeError:\n            p = DEFAULT_RESP_VERSION\n        except ValueError:\n            raise ConnectionError(\"protocol must be an integer\")\n        else:\n            if p < 2 or p > 3:\n                raise ConnectionError(\"protocol must be either 2 or 3\")\n        self.protocol = p\n        self.legacy_responses = legacy_responses\n        if self.protocol == 3 and parser_class == _RESP2Parser:\n            # If the protocol is 3 but the parser is RESP2, change it to RESP3\n            # This is needed because the parser might be set before the protocol\n            # or might be provided as a kwarg to the constructor\n            # We need to react on discrepancy only for RESP2 and RESP3\n            # as hiredis supports both\n            parser_class = _RESP3Parser\n        self.set_parser(parser_class)\n\n        self._command_packer = self._construct_command_packer(command_packer)\n        self._should_reconnect = False\n\n        # HIMPORT client-side state. `himport_registry` is the shared client-level","sourceCodeStart":908,"sourceCodeEnd":944,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/connection.py#L908-L944","documentation":"Raised in AbstractConnection.__init__ (connection.py:921-926) when int(protocol) raises ValueError — i.e. protocol was given as a non-integer, non-numeric string (e.g. 'RESP3', 'three', None handled separately). The protocol argument selects the RESP wire version and must coerce to an integer; non-numeric input is a configuration bug. It surfaces as a ConnectionError at connection start.","triggerScenarios":"Passing protocol='RESP3', protocol='three', protocol=[3], or any non-numeric value to redis.Redis/Connection. Note int('abc') raises ValueError -> this error; int(None)/int(['3']) raise TypeError -> silently fall back to DEFAULT_RESP_VERSION (so those do NOT hit this message).","commonSituations":"Reading protocol from an env var or YAML as a string like 'RESP3'; UI/config form storing the symbolic name instead of the number; misunderstanding that protocol expects 2 or 3, not the RESP name.","solutions":["Pass an integer or numeric string: protocol=3 or protocol='3'.","If loading from config, coerce and validate first: protocol=int(str(proto).strip()).","Accept only the symbolic values upstream and map them: {'RESP2':2,'RESP3':3}.","Leave protocol unset to use the library default (DEFAULT_RESP_VERSION)."],"exampleFix":"# before\nr = redis.Redis(host=h, port=p, protocol='RESP3')\n# after\nr = redis.Redis(host=h, port=p, protocol=3)","handlingStrategy":"validation","validationCode":"def resolve_protocol(raw):\n    if raw is None:\n        return None  # library default\n    try:\n        p = int(raw)\n    except (TypeError, ValueError):\n        raise ValueError(f'protocol must be a number, got {raw!r}') from None\n    if p not in (2, 3):\n        raise ValueError(f'protocol must be 2 or 3, got {p}')\n    return p\n\nr = redis.Redis(host=h, port=p, protocol=resolve_protocol(os.environ.get('REDIS_PROTOCOL')))","typeGuard":"from typing import Any\ndef is_valid_protocol(v: Any) -> bool:\n    try:\n        return int(v) in (2, 3)\n    except (TypeError, ValueError):\n        return False","tryCatchPattern":"from redis.exceptions import ConnectionError\ntry:\n    r = redis.Redis(host=h, port=p, protocol=raw_proto)\n    r.ping()\nexcept ConnectionError as e:\n    if 'protocol must be' in str(e):\n        r = redis.Redis(host=h, port=p, protocol=3)  # safe default\n    else:\n        raise","preventionTips":["Coerce and validate protocol from config/env before passing it in.","Map symbolic names ('RESP2'/'RESP3') to ints at the config boundary.","Leave protocol unset to use the library default when unsure."],"tags":["protocol","configuration","validation","resp"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}