nats-io/nats-server · error

raft: illegal peer: %q

Error message

raft: illegal peer: %q

What it means

When creating a raft group, NATS validates each peer in the knownPeers list has exactly idLen bytes. A peer ID of any other length means it is not a valid node ID, and the group creation fails with this quoted peer name in the error.

Source

Thrown at server/raft.go:396

	errBadAppendEntry    = errors.New("raft: append entry corrupt")
	errNoInternalClient  = errors.New("raft: no internal client")
	errMembershipChange  = errors.New("raft: membership change in progress")
	errRemoveLastNode    = errors.New("raft: cannot remove the last peer")
	errPeerNotFound      = errors.New("raft: peer not found")
	errNotManaged        = errors.New("raft: group membership is not managed")
	errNotLeaderless     = errors.New("raft: group is not leaderless")
	errQuorumPossible    = errors.New("raft: remaining peers could still reach quorum")
)

// This will bootstrap a raftNode by writing its config into the store directory.
func (s *Server) bootstrapRaftNode(cfg *RaftConfig, knownPeers []string, allPeersKnown bool) error {
	if cfg == nil {
		return errNilCfg
	}
	// Check validity of peers if presented.
	for _, p := range knownPeers {
		if len(p) != idLen {
			return fmt.Errorf("raft: illegal peer: %q", p)
		}
	}
	expected := len(knownPeers)
	// We need to adjust this is all peers are not known.
	if !allPeersKnown {
		s.Debugf("Determining expected peer size for JetStream meta group")
		if expected < 2 {
			expected = 2
		}
		opts := s.getOpts()
		nrs := len(opts.Routes)

		cn := s.ClusterName()
		ngwps := 0
		for _, gw := range opts.Gateway.Gateways {
			// Ignore our own cluster if specified.
			if gw.Name == cn {
				continue

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Ensure every entry in knownPeers is a genuine server-generated node ID of idLen bytes.
  2. Remove or fix the offending peer reported in %q in the error message.
  3. Re-derive the peer list from the actual cluster membership instead of a hand-written list.
  4. Validate peer IDs (length check) before constructing the raft config.

Example fix

// before
knownPeers := []string{"node-a", "node-b"}
// after
knownPeers := clusterMembers() // real idLen-byte node IDs
Defensive patterns

Strategy: validation

Validate before calling

// Validate all peer IDs before building the raft config
for _, p := range knownPeers {
    if len(p) != idLen {
        return fmt.Errorf("peer %q is not %d bytes", p, idLen)
    }
}

Type guard

func isValidPeerID(p string) bool {
    return len(p) == idLen
}

Try / catch

if _, err := createGroup(cfg, knownPeers, ...); err != nil {
    return fmt.Errorf("rebuild peer list from cluster membership: %w", err)
}

Prevention

When it happens

Trigger: Calling the raft group creation path (stream/meta assignment) with a knownPeers slice containing a malformed/short/long peer ID.

Common situations: Passing human-readable or placeholder names instead of real raft node IDs, corrupted peer state restored from disk, or custom tooling building the peer list manually.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/f04a1978c80e1a8a. Report an issue: GitHub.