nats-io/nats-server · error

bad ack floor for consumer

Error message

bad ack floor for consumer

What it means

Sanity check in consumerMemStore.Update: the reported consumer-sequence AckFloor exceeds the Delivered consumer sequence, which is impossible in a consistent state (more messages acknowledged than delivered). It guards against persisting a corrupted or forged ConsumerState.

Source

Thrown at server/memstore.go:2762

	}
	lseq := ms.state.LastSeq
	for _, db := range dbs {
		// Skip if beyond our current state.
		if first, _, _ := db.State(); first > lseq {
			continue
		}
		db.Range(func(seq uint64) bool {
			ms.removeMsg(seq, false)
			return true
		})
	}
	return nil
}

func (o *consumerMemStore) Update(state *ConsumerState) error {
	// Sanity checks.
	if state.AckFloor.Consumer > state.Delivered.Consumer {
		return fmt.Errorf("bad ack floor for consumer")
	}
	if state.AckFloor.Stream > state.Delivered.Stream {
		return fmt.Errorf("bad ack floor for stream")
	}

	// Copy to our state.
	var pending map[uint64]*Pending
	var redelivered map[uint64]uint64
	if len(state.Pending) > 0 {
		pending = make(map[uint64]*Pending, len(state.Pending))
		for seq, p := range state.Pending {
			pending[seq] = &Pending{p.Sequence, p.Timestamp}
			if seq <= state.AckFloor.Stream || seq > state.Delivered.Stream {
				return fmt.Errorf("bad pending entry, sequence [%d] out of range", seq)
			}
		}
	}
	if len(state.Redelivered) > 0 {

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Inspect the consumer state being pushed (usually from replication or a state update API) for a bogus AckFloor
  2. Reset or recreate the consumer if its state is irrecoverably inconsistent
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at server/memstore.go:2762 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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