dapr/dapr · critical
address for node %s not found in raft peers %s
Error message
address for node %s not found in raft peers %s
What it means
AddressForID (pkg/placement/peers/peers.go:28) scans the PeerInfo list parsed from --initial-cluster for the ID passed as --id (default dapr-placement-0); it is called from leadership.New at startup. If --id matches no entry key, the server cannot learn its own raft bind address and construction fails with this error. It also fires when the initial-cluster entries were parsed from malformed values that shifted the id=address pairing.
Source
Thrown at pkg/placement/peers/peers.go:35
"fmt"
"github.com/hashicorp/raft"
)
// PeerInfo represents raft peer node information.
type PeerInfo struct {
ID string
Address string
}
func AddressForID(id string, nodes []PeerInfo) (string, error) {
for _, node := range nodes {
if node.ID == id {
return node.Address, nil
}
}
return "", fmt.Errorf("address for node %s not found in raft peers %s", id, nodes)
}
func BootstrapConfig(peers []PeerInfo) (*raft.Configuration, error) {
raftConfig := &raft.Configuration{
Servers: make([]raft.Server, len(peers)),
}
for i, p := range peers {
raftConfig.Servers[i] = raft.Server{
ID: raft.ServerID(p.ID),
Address: raft.ServerAddress(p.Address),
}
}
return raftConfig, nil
}
View on GitHub (pinned to 74ad417027)
Solutions
- Set --id to exactly one key present in --initial-cluster (keys are the id= prefixes).
- Regenerate --initial-cluster covering every replica with consistent keys (the chart derives both from the statefulset).
- Print/validate the parsed peers before start: each entry must be id=host:port with unique ids.
Example fix
# before --id=p1 --initial-cluster=dapr-placement-0=127.0.0.1:8201 # p1 not a peer key # after --id=dapr-placement-0 --initial-cluster=dapr-placement-0=127.0.0.1:8201
Defensive patterns
Strategy: validation
Validate before calling
// Validate flags before leadership.New (where AddressForID is called).
func validatePlacementFlags(id string, peers []peers.PeerInfo) error {
if id == "" {
return errors.New("--id is required")
}
if len(peers) == 0 {
return errors.New("--initial-cluster parsed to zero peers")
}
for _, p := range peers {
if p.ID == id {
return nil
}
}
return fmt.Errorf("--id %q not found in --initial-cluster keys %v", id, peerIDs(peers))
} Type guard
func hasPeer(id string, peers []peers.PeerInfo) bool {
for _, p := range peers {
if p.ID == id {
return true
}
}
return false
} Try / catch
leadershipSvc, err := leadership.New(leadership.Options{ID: id, Peers: peers, /* ... */})
if err != nil {
// startup config error: fix --id / --initial-cluster key mismatch; do not retry
log.Fatalf("placement identity not in raft peers: %v", err)
} Prevention
- Generate --id and --initial-cluster from the same source (statefulset name + ordinal) in templates.
- Never scale replicas by editing flags alone — regenerate the whole initial-cluster list.
- Add a container startup check that fails fast with a readable message when id is missing from peers.
When it happens
Trigger: --id=p1 while --initial-cluster keys are dapr-placement-0=...; --initial-cluster empty or malformed so the parsed peer list is empty; statefulset renamed but flags not updated; helm overrides changing replica count without regenerating initial-cluster.
Common situations: Hand-rolled multi-node placement deployments where id names drift from peer keys; local test harnesses assembling flags manually.
Related errors
- failed to create raft: %w
- failed to create raft listener: %w
- kubeconfig flag is only valid in --mode=kubernetes
- actors: state store does not exist or incorrectly configured
- lost leadership
AI-assisted analysis of dapr/dapr@74ad417027 (2026-08-16).
Data as JSON: /api/errors/e835a57617ccda7f.
Report an issue: GitHub.