hashicorp/nomad · error
unsupported minimum common raft protocol version
Error message
unsupported minimum common raft protocol version
What it means
TransferLeadershipToPeer (operator raft transfer-leadership RPC) refuses to run when the cluster-wide minimum common Raft protocol version is below 3, since Raft protocol v3 is required for explicit leadership transfer. The server returns a 400 with this message after logging a warning with required vs current versions.
Source
Thrown at nomad/operator_endpoint.go:242
// currently no leader.
if reply.From.Address == "" || reply.From.ID == "" {
reply.Err = structs.ErrNoLeader
return structs.NewErrRPCCoded(http.StatusServiceUnavailable, structs.ErrNoLeader.Error())
}
// while this is a somewhat more expensive test than later ones, if this
// test fails, they will _never_ be able to do a transfer. We do this after
// ACL checks though, so as to not leak cluster info to non-validated users.
minRaftProtocol, err := op.srv.MinRaftProtocol()
if err != nil {
reply.Err = err
return structs.NewErrRPCCoded(http.StatusInternalServerError, err.Error())
}
// TransferLeadership is not supported until Raft protocol v3 or greater.
if minRaftProtocol < 3 {
op.logger.Warn("unsupported minimum common raft protocol version", "required", "3", "current", minRaftProtocol)
reply.Err = errors.New("unsupported minimum common raft protocol version")
return structs.NewErrRPCCoded(http.StatusBadRequest, reply.Err.Error())
}
var kind, testedVal string
// The request must provide either an ID or an Address, this lets us validate
// the request
req.Validate()
switch {
case req.ID != "":
kind, testedVal = "id", string(req.ID)
case req.Address != "":
kind, testedVal = "address", string(req.Address)
default:
reply.Err = errors.New("must provide peer id or address")
return structs.NewErrRPCCoded(http.StatusBadRequest, reply.Err.Error())
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Upgrade all Nomad servers to a version using Raft protocol 3+ and remove any raft_protocol < 3 settings in server blocks
- Check `nomad operator raft list-peers` (or the agent members output) to find the peer still on an older protocol and upgrade/restart it
- As a workaround, let Raft transfer leadership naturally (stop the leader) instead of using explicit transfer
Example fix
// before
server {
raft_protocol = 2
}
// after
server {
raft_protocol = 3
} Defensive patterns
Strategy: validation
Validate before calling
peers, _, _ := client.Operator().RaftPeers(nil)
for _, p := range peers {
if p.RaftProtocol < 3 {
return fmt.Errorf("peer %s on raft protocol %d; upgrade before transfer", p.ID, p.RaftProtocol)
}
} Try / catch
resp, err := client.Operator().RaftTransferLeadership(peerID, addr, nil)
if err != nil && strings.Contains(err.Error(), "unsupported minimum common raft protocol") {
// upgrade the lagging server, then retry
} Prevention
- Keep all servers on Nomad versions using raft protocol 3+
- Never lower raft_protocol below 3 in server configs
- Check min common raft protocol after every server join/upgrade
When it happens
Trigger: Running `nomad operator raft transfer-leadership -peer-id <id>` (or the equivalent HTTP POST to /v1/operator/raft/transfer-leadership) while any server in the cluster still speaks Raft protocol v2 or lower (Nomad < 0.8 servers present, or min_raft_protocol/raft_protocol lowered below 3 on a peer).
Common situations: Mixed-version clusters during rolling upgrades; operators manually setting raft_protocol = 2 in server config for legacy compatibility; newly added old-version servers dragging down min common protocol.
Related errors
- No cluster leader
- failed to reset heartbeat since server is not leader
- must provide peer id or address
- No servers found
- Failed to start Raft: %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/b2020e3f03428a7f.
Report an issue: GitHub.