nats-io/nats-server · error
unable to persist session %q (seq=%v): invalid pub ack respo
Error message
unable to persist session %q (seq=%v): invalid pub ack response
What it means
Returned when the JetStream publish of the session record succeeds without error but the response is unusable: resp is nil or resp.PubAck is nil, so the new sequence cannot be confirmed. This is a defensive guard against an malformed/missing acknowledgement.
Source
Thrown at server/mqtt.go:3439
bb := bytes.Buffer{}
bb.WriteString(hdrLine)
bb.WriteString(JSExpectedLastSubjSeq)
bb.WriteString(":")
bb.WriteString(strconv.FormatInt(int64(seq), 10))
bb.WriteString(CR_LF)
bb.WriteString(CR_LF)
hdr = bb.Len()
bb.Write(b)
b = bb.Bytes()
}
resp, err := sess.jsa.storeSessionMsg(domainTk, cidHash, hdr, b)
if err != nil {
return fmt.Errorf("unable to persist session %q (seq=%v): %v", ps.ID, seq, err)
}
// Guard before dereferencing below.
if resp == nil || resp.PubAck == nil {
return fmt.Errorf("unable to persist session %q (seq=%v): invalid pub ack response", ps.ID, seq)
}
sess.mu.Lock()
sess.seq = resp.Sequence
sess.mu.Unlock()
return nil
}
// Clear the session.
//
// Runs from the client's readLoop.
// Lock not held on entry, but session is in the locked map.
func (sess *mqttSession) clear(noWait bool) error {
var durs []string
var pubRelDur string
sess.mu.Lock()
id := sess.id
seq := sess.seqView on GitHub (pinned to 3a66a489d2)
Solutions
- Retry the CONNECT / session persistence operation
- Upgrade all servers to a consistent version (likely internal bug fixed upstream)
- Check JetStream health and logs around the time of the failure
- Report/inspect the wrapped scenario: err==nil but PubAck missing
Example fix
// before // err==nil, resp.PubAck==nil -> error // after // upgrade server binaries to matching versions and restart the cluster null
Defensive patterns
Strategy: try-catch
Try / catch
try {
await mqttConnect()
} catch (e) {
if (String(e).includes('invalid pub ack response')) {
log.error('JetStream returned malformed pub ack; check cluster version consistency', e)
await mqttConnect() // one retry
} else { throw e }
} Prevention
- Keep all servers on the same binary version
- Watch for JetStream API anomalies in server logs
- Retry CONNECT once; persistent occurrences indicate a bug to report upstream
- Maintain a support bundle (jsz, logs) when this occurs
When it happens
Trigger: storeSessionMsg returns resp == nil or resp.PubAck == nil despite err == nil — an unexpected/empty JetStream publish acknowledgement, typically from an API/transport anomaly or a bug in the async pub path.
Common situations: JetStream API returning malformed acks during instability; mixed server versions in a cluster; internal async-publish race.
Related errors
- ack wait must be a positive value
- JS API timeout must be a positive value
- mqtt requires JetStream to be enabled if running in standalo
- mqtt: consumer_replicas (%v) cannot be higher than stream_re
- unable to connect: %v
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/f933d5f14d8e5459.
Report an issue: GitHub.