--- id: "bug-320" status: "fixed" status_updated: "2026-09-24" status_note: "" component: "controller" severity: "unknown" timestamp: "2026-06-05T06:50:00Z" last_seen: "2026-09-19T09:00:00Z" occurrences: 1 files: ["src/controller/ha.c"] tags: ["ha", "majority-convergence", "n_peers", "off-by-one", "integration-test"] related: [] legacy: true --- # bug-320: 3-node startup: majority convergence never fires; cluster falls through to committing_timeout… ## Description 3-node startup: majority convergence never fires; cluster falls through to committing_timeout degraded-mode WARN ## Environment _Not recorded (migrated from buglog.json)._ ## Reproduction _Not recorded (migrated from buglog.json)._ ## Root cause ha->n_peers was set to candidates_count (3, total including self) in ha_start_election_async. ha_check_majority_convergence loops i=0..n_peers-1 checking standby_converged[], but standby_converged[] is indexed by votes_idx (relative, self excluded: 0..n_other-1). With n_peers=3, it checked standby_converged[2] which is never set, so n_converged (2) < n_peers (3) always — majority convergence path could never succeed. ## Fix Changed ha->n_peers = n_peers to ha->n_peers = n_other (= n_peers-1 = other-node count). Moved the assignment after n_other is computed. ha_repl_ack_received quorum formula (ha->n_peers+2)/2 still yields correct majority for both old and new value. ## Verification _Not recorded (migrated from buglog.json)._ ## References _Not recorded (migrated from buglog.json)._