{"record":{"id":"3d297feb3a284f64","repo":"redis/redis-py","slug":"no-master-found-for-service-name-r-error-info-3d297f","errorCode":null,"errorMessage":"No master found for {service_name!r}{error_info}","messagePattern":"No master found for (.+?)(.+?)","errorType":"exception","errorClass":"MasterNotFoundError","httpStatus":null,"severity":"critical","filePath":"redis/sentinel.py","lineNumber":384,"sourceCode":"            state = masters.get(service_name)\n            if state and self.check_master_state(state, service_name):\n                # Put this sentinel at the top of the list\n                self.sentinels[0], self.sentinels[sentinel_no] = (\n                    sentinel,\n                    self.sentinels[0],\n                )\n\n                ip = (\n                    self._force_master_ip\n                    if self._force_master_ip is not None\n                    else state[\"ip\"]\n                )\n                return ip, state[\"port\"]\n\n        error_info = \"\"\n        if len(collected_errors) > 0:\n            error_info = f\" : {', '.join(collected_errors)}\"\n        raise MasterNotFoundError(f\"No master found for {service_name!r}{error_info}\")\n\n    def filter_slaves(self, slaves):\n        \"Remove slaves that are in an ODOWN or SDOWN state\"\n        slaves_alive = []\n        for slave in slaves:\n            if slave[\"is_odown\"] or slave[\"is_sdown\"]:\n                continue\n            slaves_alive.append((slave[\"ip\"], slave[\"port\"]))\n        return slaves_alive\n\n    def filter_replicas(self, replicas):\n        \"\"\"Remove replicas that are in an ODOWN or SDOWN state.\n\n        This is an alias for :py:meth:`filter_slaves`,\n        using the preferred Redis 5.0+ terminology.\n        \"\"\"\n        return self.filter_slaves(replicas)\n","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/sentinel.py#L366-L402","documentation":"Raised by Sentinel.discover_master() (redis/sentinel.py:384) after iterating every configured sentinel and finding none that reports a master in a healthy state for service_name. A sentinel 'passes' only if sentinel_masters() returns the service, state['is_master'] is True, the node is not in SDOWN/ODOWN, and num-other-sentinels >= self.min_other_sentinels (check_master_state, sentinel.py:343-349). error_info appends any per-sentinel ConnectionError/TimeoutError collected during the loop, so the message tells you which sentinels were unreachable.","triggerScenarios":"First connection (or re-discovery) calls discover_master(service_name); every sentinel either raises ConnectionError/TimeoutError (collected into error_info), or returns no state for service_name, or returns state failing check_master_state (not master, sdown, odown, or insufficient peer sentinels). The loop completes with no return and raises MasterNotFoundError at sentinel.py:384.","commonSituations":"All sentinels unreachable (network partition, wrong host/port); service_name typo so no sentinel knows it; quorum not yet reached mid-failover (old master down, new master not elected); min_other_sentinels configured higher than (sentinel_count - 1); client isolated from the sentinel quorum.","solutions":["Inspect error_info in the message — it lists each unreachable sentinel and the underlying error; fix reachability first.","Verify service_name with `redis-cli -p <sentinel_port> SENTINEL masters` against each sentinel.","If mid-failover, retry with backoff — discovery succeeds once a new master is elected and quorum agrees.","Lower Sentinel(..., min_other_sentinels=N) if it exceeds your actual sentinel count minus one.","Confirm network connectivity (telnet/ping) from the client to every sentinel host:port in the sentinels list."],"exampleFix":"# before\ns = redis.sentinel.Sentinel([('sent1', 26379)], min_other_sentinels=3)\ns.master_for('mymaster')  # MasterNotFoundError: No master found for 'mymaster' : ...\n\n# after: retry with backoff and verify service_name/quorum\nimport time, redis\nfor attempt in range(10):\n    try:\n        s.discover_master('mymaster'); break\n    except redis.exceptions.MasterNotFoundError:\n        time.sleep(0.2 * (2 ** attempt))\nelse:\n    raise","handlingStrategy":"retry","validationCode":"import socket\n\ndef sentinels_reachable(sentinels, timeout=0.5) -> bool:\n    # call before relying on master discovery\n    for host, port in sentinels:\n        try:\n            with socket.create_connection((host, port), timeout=timeout):\n                pass\n        except OSError:\n            return False\n    return True","typeGuard":null,"tryCatchPattern":"import redis.exceptions, time\n\ndef discover_master_with_retry(sentinel, service_name, retries=10, base=0.2):\n    last = None\n    for attempt in range(retries):\n        try:\n            return sentinel.discover_master(service_name)\n        except redis.exceptions.MasterNotFoundError as e:\n            last = e\n            time.sleep(base * (2 ** attempt))\n    raise last","preventionTips":["Use a sentinel list with >= 3 nodes so quorum survives one being down.","Set min_other_sentinels <= (sentinel_count - 1) to avoid over-strict quorum.","Verify service_name against `SENTINEL masters` on every sentinel during deploy."],"tags":["sentinel","master-discovery","failover","high-availability"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}