## TL;DR
Patroni reports "no leader" when the distributed consensus store says no member holds the lock, which usually means the old leader lost its lock and no replica was eligible to take over. Check the consensus store first, then each member's logs for why promotion failed, then promote a healthy replica manually if the cluster cannot elect one. Act on the members, not on Postgres itself, until a leader exists.

```text
no leader
```

## Steps

1. Ask Patroni which members are alive and what each one thinks the leader is.

```bash
patronictl -c [CONFIG_FILE] list
patronictl -c [CONFIG_FILE] topology
```

Expected: a table of members with roles and lag. If the Leader column is empty everywhere but members are running, the lock expired without a successful promotion.

2. Check the consensus store directly for the leader lock key.

```bash
ETCDCTL_API=3 etcdctl --endpoints=[DCS_ENDPOINTS] get [SCOPE]/leader --print-value-only
```

Expected: either a member name (stale lock the members cannot see, which is a connectivity problem) or nothing (the lock genuinely expired). This tells you whether to fix networking or fix member eligibility.

3. Read the last promotion attempt on the most caught-up replica.

```bash
journalctl -u patroni --since '30 minutes ago' | grep -i -E 'promot|demot|lock'
```

Expected: lines showing why promotion was refused, usually replication lag past the allowed threshold, a failed restart of Postgres, or a timeline mismatch.

4. Fail over to the best replica by hand when the cluster will not elect one.

```bash
patronictl -c [CONFIG_FILE] failover --candidate [REPLICA_NAME] --force
```

Expected: the candidate promotes, the other members re-point as replicas, and `patronictl list` shows a leader again. Verify with a write query before declaring recovery.

## When to use

- `patronictl list` shows no leader, or applications report they cannot write while replicas look healthy.
- Right after a network partition, consensus-store outage, or maintenance on the old leader.
- Logs mention "failed to bootstrap from leader" on a new member trying to join.

## When not to use

- Postgres is down on all members (that is a Postgres crash problem, not an election problem).
- The consensus store itself is down (fix etcd or Consul first; Patroni cannot elect without it).
- A single replica is lagging while a leader exists (that is replication lag, not a leader problem).

## Why it happens

Patroni members renew a lock in the consensus store; whoever holds it is the leader. If the leader loses contact with the store, it demotes itself, and replicas race to take the lock. A replica refuses to promote if it is too far behind, cannot restart Postgres cleanly, or cannot reach the old leader to get a timeline history. When every candidate refuses or the store is unreachable, you get "no leader" with healthy-looking members.

## Edge cases

- Split-brain risk: if the old leader comes back thinking it still leads, the consensus lock decides, not the Postgres process; fence the old leader before promoting.
- `failed to bootstrap from leader` on a fresh member usually means the leader it was told to clone from changed mid-clone; retry after a leader is stable.
- Synchronous replication settings can block promotion when the required sync standby is gone; check `synchronous_standby_names` before forcing failover.
- After manual failover, old replicas with divergent timelines need a rewind or rebuild; check `pg_rewind` eligibility or re-clone them.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_gKrMNzrDwHci4toes7aMQQ
