nats-io/nats-server · error
DN ended with incomplete type, value pair
Error message
DN ended with incomplete type, value pair
What it means
Returned by consumerMemStore.Update when AckFloor.Stream exceeds Delivered.Stream. Stream-wise ack floor must always be <= delivered stream sequence; a state violating this is rejected outright. Same invariant family as the consumer ack floor check, but on the stream sequence namespace.
Source
Thrown at internal/ldap/dn.go:208
rdn.Attributes = make([]*AttributeTypeAndValue, 0)
}
case char == ' ' && buffer.Len() == 0:
// ignore unescaped leading spaces
continue
default:
if char == ' ' {
// Track unescaped spaces in case they are trailing and we need to remove them
unescapedTrailingSpaces++
} else {
// Reset if we see a non-space char
unescapedTrailingSpaces = 0
}
buffer.WriteByte(char)
}
}
if buffer.Len() > 0 {
if len(attribute.Type) == 0 {
return nil, errors.New("DN ended with incomplete type, value pair")
}
attribute.Value = stringFromBuffer()
rdn.Attributes = append(rdn.Attributes, attribute)
dn.RDNs = append(dn.RDNs, rdn)
}
return dn, nil
}
// Equal returns true if the DNs are equal as defined by rfc4517 4.2.15 (distinguishedNameMatch).
// Returns true if they have the same number of relative distinguished names
// and corresponding relative distinguished names (by position) are the same.
func (d *DN) Equal(other *DN) bool {
if len(d.RDNs) != len(other.RDNs) {
return false
}
for i := range d.RDNs {
if !d.RDNs[i].Equal(other.RDNs[i]) {
return falseView on GitHub (pinned to 3a66a489d2)
Solutions
- Fix the code advancing the ack floor so it never exceeds delivered stream sequence
- Clamp AckFloor.Stream to Delivered.Stream before Update
- Re-derive state from stored message sequences if it came from a suspect source
Example fix
// before
st.AckFloor.Stream = 500; st.Delivered.Stream = 400
consumer.Update(st)
// after
if st.AckFloor.Stream > st.Delivered.Stream {
st.AckFloor.Stream = st.Delivered.Stream
}
consumer.Update(st) Defensive patterns
Strategy: validation
Validate before calling
if st.AckFloor.Stream > st.Delivered.Stream {
st.AckFloor.Stream = st.Delivered.Stream // clamp
}
consumer.Update(st) Try / catch
if err := consumer.Update(st); err != nil {
if strings.Contains(err.Error(), "bad ack floor for stream") {
st.AckFloor.Stream = st.Delivered.Stream
err = consumer.Update(st)
}
} Prevention
- Never compute ack floor and delivered sequences independently
- Validate restored/migrated states before applying
- Use min()/clamping when merging partial state updates
When it happens
Trigger: Calling consumerMemStore.Update(state) where state.AckFloor.Stream > state.Delivered.Stream.
Common situations: Restoring/migrating consumer state from a snapshot with mismatched sequences; concurrent updates applied out of order; bugs in ack-floor advancement logic.
Related errors
- incomplete type, value pair
- errors.New(strings.Join(errs, "\n"))
- bad ack floor for stream
- bad pending entry, sequence [%d] out of range
- got corrupted escaped character
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/4ca33fe5d6988743.
Report an issue: GitHub.