{"id":"913b9b47a5ecd9de","repo":"pika/pika","slug":"timeout-must-1-but-got-timeout-r","errorCode":null,"errorMessage":"timeout must >= 1, but got {timeout!r}","messagePattern":"timeout must >= 1, but got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pika/heartbeat.py","lineNumber":38,"sourceCode":"    _STALE_CONNECTION = 'No activity or too many missed heartbeats in the last %i seconds'\n\n    def __init__(self, connection, timeout) -> None:\n        \"\"\"\n        Create an object that will check for activity on the provided connection as well as receive\n        heartbeat frames from the broker. The timeout parameter defines a window within which this\n        activity must happen. If not, the connection is considered dead and closed.\n\n        The value must be >= 1. The value passed for timeout is also used to calculate an interval\n        at which a heartbeat frame is sent to the broker. The interval is equal to the timeout value\n        divided by two.\n\n        :param connection: Connection object\n        :param timeout: Connection idle timeout. If no activity occurs on the connection nor\n            heartbeat frames received during the timeout window the connection will be closed. The\n            interval used to send heartbeats is calculated from this value by dividing it by two.\n        \"\"\"\n        if timeout < 1:\n            raise ValueError(f'timeout must >= 1, but got {timeout!r}')\n\n        self._connection = connection\n\n        # Note: see the following documents:\n        # https://www.rabbitmq.com/heartbeats.html#heartbeats-timeout\n        # https://github.com/pika/pika/pull/1072\n        # https://groups.google.com/d/topic/rabbitmq-users/Fmfeqe5ocTY/discussion\n        # There is a certain amount of confusion around how client developers\n        # interpret the spec. The spec talks about 2 missed heartbeats as a\n        # *timeout*, plus that any activity on the connection counts for a\n        # heartbeat. This is to avoid edge cases and not to depend on network\n        # latency.\n        self._timeout = timeout\n\n        self._send_interval = float(timeout) / 2\n\n        # Note: Pika will calculate the heartbeat / connectivity check interval\n        # by adding 5 seconds to the negotiated timeout to leave a bit of room","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/pika/pika/blob/295ad9e5795061d759b694ab1fcb33cd381d8c49/pika/heartbeat.py#L20-L56","documentation":"HeartbeatChecker.__init__ (heartbeat.py:37-38) requires its timeout argument to be at least 1; anything smaller raises ValueError. The value drives both the heartbeat send interval (timeout/2) and the stale-connection check interval (timeout+5), so a zero or fractional timeout would produce a zero or negative send interval and break the scheduler. The check is a hard floor, not a recommendation.","triggerScenarios":"Negotiating a heartbeat of 0 with the broker would normally disable the checker (_create_heartbeat_checker guards with heartbeat > 0), but this error surfaces if HeartbeatChecker is constructed directly with a value < 1, or if a custom heartbeat callback returns 0 or a fractional value that bypasses the int/positivity guard at line 1671. Constructing pika.heartbeat.HeartbeatChecker(conn, 0) reproduces it.","commonSituations":"Directly instantiating HeartbeatChecker in tests or custom adapters with a 0 or negative timeout; a heartbeat negotiation callback returning a float < 1; manually setting params.heartbeat to a sub-1 value after tune.","solutions":["Ensure the heartbeat value passed is an integer >= 1 (use 0 only to disable, and let Connection._create_heartbeat_checker skip construction).","If you need to disable heartbeats, set ConnectionParameters(heartbeat=0) rather than building a HeartbeatChecker manually.","When using a heartbeat callback, clamp the return to max(1, desired) and return an int."],"exampleFix":"# before\nchecker = pika.heartbeat.HeartbeatChecker(conn, 0)\n# after\nparams = pika.ConnectionParameters(heartbeat=0)  # disables heartbeat entirely","handlingStrategy":"validation","validationCode":"if isinstance(params.heartbeat, int) and params.heartbeat < 1:\n    # 0 disables; any other sub-1 int is invalid\n    params.heartbeat = 0 if params.heartbeat == 0 else 1\n# or, for a custom checker:\ntimeout = max(1, int(timeout)) if timeout else 0\nif timeout:\n    checker = pika.heartbeat.HeartbeatChecker(conn, timeout)","typeGuard":"def is_valid_heartbeat_timeout(v: int) -> bool:\n    return isinstance(v, int) and v >= 1","tryCatchPattern":"try:\n    checker = pika.heartbeat.HeartbeatChecker(conn, timeout)\nexcept ValueError:\n    timeout = 60\n    checker = pika.heartbeat.HeartbeatChecker(conn, timeout)","preventionTips":["Let ConnectionParameters manage heartbeat; do not construct HeartbeatChecker yourself unless you are writing an adapter.","Treat 0 as 'disable' everywhere, and keep all other values >= 1."],"tags":["heartbeat","config","value-error","connection"],"analyzedSha":"295ad9e5795061d759b694ab1fcb33cd381d8c49","analyzedAt":"2026-08-04T20:47:41.389Z","schemaVersion":2}