nats-io/nats-server · critical
%w for stream '%s > %s'
Error message
%w for stream '%s > %s'
What it means
When a stream message consumer/catch-up routine (processInboundMsg on a mirror/source or raft catch-up path) is running and the raft/node loses its leader, it retries with a sleep interval. If the group is still leaderless on the first retry (numRetries == 0 and n.Leaderless()), it aborts with fmt.Errorf("%w for stream '%s > %s'", errCatchupAbortedNoLeader, ...), wrapping errCatchupAbortedNoLeader so callers can detect the catch-up was aborted because there is no raft leader to sync from.
Source
Thrown at server/jetstream_cluster.go:12496
const maxRetries = 3
var numRetries int
RETRY:
// On retry, we need to release the semaphore we got. Call will be no-op
// if releaseSem boolean has not been set to true on successfully getting
// the semaphore.
releaseSyncOutSem()
if n.Leaderless() {
// Prevent us from spinning if we've installed a snapshot from a leader but there's no leader online.
// We wait a bit to check if a leader has come online in the meantime, if so we can continue.
var canContinue bool
if numRetries == 0 {
time.Sleep(startInterval)
canContinue = !n.Leaderless()
}
if !canContinue {
return fmt.Errorf("%w for stream '%s > %s'", errCatchupAbortedNoLeader, mset.account(), mset.name())
}
}
// If we have a sub clear that here.
if sub != nil {
s.sysUnsubscribe(sub)
sub = nil
}
if !s.isRunning() {
return ErrServerNotRunning
}
numRetries++
if numRetries > maxRetries {
// Force a hard reset here.
return errCatchupTooManyRetries
}View on GitHub (pinned to 3a66a489d2)
Solutions
- Restore quorum: bring the required number of JetStream servers back online so a leader can be elected.
- Check `nats server request JetStream` / `nats str info <stream>` for peer/leader status and fix any partitioned node.
- After quorum is restored the catch-up retries; if it stays aborted, restart the affected replica server.
- Space out rolling restarts so the leader is never removed before a new one is elected.
Defensive patterns
Strategy: retry
Validate before calling
// before starting mirrors/sources or relying on catch-up, check leader presence
si, _ := js.StreamInfo(name)
if si.Cluster != nil && si.Cluster.Leader == "" {
// leaderless: wait before triggering work that requires catch-up
} Try / catch
err := doCatchup()
if errors.Is(err, errCatchupAbortedNoLeader) {
// exponential backoff until the group elects a leader
retryWithBackoff(doCatchup)
} Prevention
- Maintain quorum: never take down a majority of JetStream peers at once.
- Sequence rolling restarts so a new leader is elected between restarts.
- Alert on leaderless streams via stream info cluster.leader.
- Monitor network partitions and raft election timeouts.
When it happens
Trigger: A stream replica (or mirror/source consumer) attempts to catch up while the stream's raft group has no elected leader — e.g. the leader just crashed, a majority of peers are down, or a rolling restart removed the leader before a new election completed.
Common situations: Clusters operating with degraded quorum; maintenance windows where multiple JetStream servers restart simultaneously; network partitions isolating the leader.
Related errors
- shutting down
- consumer write error: %v
- raft: illegal peer: %q
- JS_CONSUMER_OFFLINE
- stream assignment or group missing
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/b24336278484513b.
Report an issue: GitHub.