{"id":"d04f2935d71f0dd4","repo":"redis/redis-py","slug":"health-check-probes-must-be-greater-than-0","errorCode":null,"errorMessage":"health_check_probes must be greater than 0","messagePattern":"health_check_probes must be greater than 0","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"redis/asyncio/multidb/healthcheck.py","lineNumber":357,"sourceCode":"\nclass HealthCheckPolicies(Enum):\n    HEALTHY_ALL = HealthyAllPolicy\n    HEALTHY_MAJORITY = HealthyMajorityPolicy\n    HEALTHY_ANY = HealthyAnyPolicy\n\n\nDEFAULT_HEALTH_CHECK_POLICY: HealthCheckPolicies = HealthCheckPolicies.HEALTHY_ALL\n\n\nclass AbstractHealthCheck(HealthCheck):\n    def __init__(\n        self,\n        health_check_probes: int = DEFAULT_HEALTH_CHECK_PROBES,\n        health_check_delay: float = DEFAULT_HEALTH_CHECK_DELAY,\n        health_check_timeout: float = DEFAULT_HEALTH_CHECK_TIMEOUT,\n    ):\n        if health_check_probes < 1:\n            raise ValueError(\"health_check_probes must be greater than 0\")\n        self._health_check_probes = health_check_probes\n        self._health_check_delay = health_check_delay\n        self._health_check_timeout = health_check_timeout\n\n    @property\n    def health_check_probes(self) -> int:\n        return self._health_check_probes\n\n    @property\n    def health_check_delay(self) -> float:\n        return self._health_check_delay\n\n    @property\n    def health_check_timeout(self) -> float:\n        return self._health_check_timeout\n\n    @abstractmethod\n    async def check_health(self, database, hc_client: AsyncRedisClientT) -> bool:","sourceCodeStart":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/asyncio/multidb/healthcheck.py#L339-L375","documentation":"Raised by AbstractHealthCheck.__init__ (redis/asyncio/multidb/healthcheck.py:357) when the health_check_probes argument is less than 1. The multidb health-check subsystem needs at least one probe attempt to determine database liveness, so zero/negative is rejected at construction time before any check runs.","triggerScenarios":"Instantiating PingHealthCheck, LagAwareHealthCheck, or any AbstractHealthCheck subclass with health_check_probes=0 or a negative value; passing a probes count sourced from an empty/zeroed config value into the DatabaseConfig/health-check construction.","commonSituations":"Reading probe count from an environment variable or YAML config that defaults to 0; copying a config block and zeroing the probes field to \"disable\" probing (the API has no disable-by-zero semantics); arithmetic that underflows to 0.","solutions":["Set health_check_probes to a positive integer (the DEFAULT_HEALTH_CHECK_PROBES constant is the intended default).","If you meant to disable health checks, do not construct a health-check object at all; instead omit the policy / use a no-op health strategy.","Validate the config value (int(v) > 0) before passing it into the health-check constructor."],"exampleFix":"// before\nhc = PingHealthCheck(health_check_probes=0)\n// after\nhc = PingHealthCheck(health_check_probes=DEFAULT_HEALTH_CHECK_PROBES)","handlingStrategy":"validation","validationCode":"from redis.asyncio.multidb.healthcheck import DEFAULT_HEALTH_CHECK_PROBES\nif not isinstance(probes, int) or probes < 1:\n    probes = DEFAULT_HEALTH_CHECK_PROBES\nhc = PingHealthCheck(health_check_probes=probes)","typeGuard":"def is_valid_probe_count(v) -> bool:\n    return isinstance(v, int) and v >= 1","tryCatchPattern":"try:\n    hc = PingHealthCheck(health_check_probes=probes)\nexcept ValueError as e:\n    raise SystemConfigError(f\"bad health_check_probes: {e}\") from e","preventionTips":["Never reuse a zero value to mean 'disabled'; omit the health check instead.","Centralize health-check construction behind a helper that validates probes."],"tags":["config","validation","multidb","healthcheck"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}