nats-io/nats-server · error
failed to update stream config: %w
Error message
failed to update stream config: %w
What it means
The retained messages stream existed but its subjects did not match the expected single $MQTT.rmsgs subject, so the server attempted a stream update via updateStream; that update failed and the underlying JetStream error is wrapped here. It signals a stream config mismatch that could not be repaired automatically.
Source
Thrown at server/mqtt.go:1535
}
needToTransfer = false
default:
needToTransfer = si.Config.MaxMsgsPer != 1
}
// Guard before dereferencing si.Config below.
if si == nil {
return nil, fmt.Errorf("could not look up or create the retained messages stream for account %q", accName)
}
// Doing this check outside of above if/else due to possible race when
// creating the stream.
wantedSubj := mqttRetainedMsgsStreamSubject + ">"
if len(si.Config.Subjects) != 1 || si.Config.Subjects[0] != wantedSubj {
// Update only the Subjects at this stage, not MaxMsgsPer yet.
si.Config.Subjects = []string{wantedSubj}
if si, err = jsa.updateStream(&si.Config); err != nil {
return nil, fmt.Errorf("failed to update stream config: %w", err)
}
}
transferRMS := func() error {
if !needToTransfer {
return nil
}
as.transferRetainedToPerKeySubjectStream(s)
// We need another lookup to have up-to-date si.State values in order
// to load all retained messages.
si, err = lookupStream(mqttRetainedMsgsStreamName, "retained messages")
if err != nil {
return err
}
needToTransfer = false
return nilView on GitHub (pinned to 3a66a489d2)
Solutions
- Delete the existing retained messages stream ($MQTT.rmsgs related) while no MQTT clients are connected and let the server recreate it
- Compare the stream's config with what the server expects and correct subjects manually via nats stream update
- Check server logs for the wrapped update error (e.g. invalid config change, no responders) and address it
- Run all server nodes on the same NATS Server version to avoid config schema mismatches
Example fix
// before nats stream info $MQTT.rmsgs # subjects: ["foo"] // after nats stream rm $MQTT.rmsgs --force # restart MQTT clients; server recreates stream with subject $MQTT.rmsgs.>
Defensive patterns
Strategy: retry
Validate before calling
// Verify the stream config matches what the server expects:
js, _ := nc.JetStream()
si, err := js.StreamInfo("$MQTT.rmsgs")
if err == nil {
subjects := si.Config.Subjects
if len(subjects) != 1 || subjects[0] != "$MQTT.rmsgs.>" {
// mismatch: delete stream during maintenance so server recreates it
}
} Try / catch
if err != nil && strings.Contains(err.Error(), "failed to update stream config") {
log.Printf("retained stream config mismatch: %v", err)
// schedule maintenance deletion: nats stream rm $MQTT.rmsgs --force
} Prevention
- Do not hand-edit internal $MQTT streams
- Upgrade all servers together; never run mixed versions on one JS domain
- If you must recreate the stream, do it with no MQTT clients connected
When it happens
Trigger: An existing stream with the retained-messages name was created manually or by an older server version with different subjects; updateStream's JS API request fails (invalid config change, no permission, timeout, resources).
Common situations: Upgrading from an older NATS server whose MQTT retained stream used a different subject config; operator manually created/edited the stream; JetStream API errors like invalid stream configuration during update.
Related errors
- invalid stream update response: missing stream info
- 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
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/2244fe295c70a81f.
Report an issue: GitHub.