nats-io/nats-server · error
storage type can not be updated
Error message
storage type can not be updated
What it means
A consumer update tried to change MemoryStorage, i.e. switch the consumer between memory and file storage. Storage type is fixed at creation, so checkNewConsumerConfig rejects any difference. The request fails with this error.
Source
Thrown at server/consumer.go:2538
} else {
burst = int(acc.srv.getOpts().MaxPayload)
}
}
o.rlimit = rate.NewLimiter(rl, burst)
}
// Check if new consumer config allowed vs old.
func (acc *Account) checkNewConsumerConfig(cfg, ncfg *ConsumerConfig) error {
if reflect.DeepEqual(cfg, ncfg) {
return nil
}
// Something different, so check since we only allow certain things to be updated.
if cfg.DeliverPolicy != ncfg.DeliverPolicy {
return errors.New("deliver policy can not be updated")
}
if cfg.MemoryStorage != ncfg.MemoryStorage {
return errors.New("storage type can not be updated")
}
// Direct and Sourcing classify the consumer for its whole lifetime, which the
// stream relies on when walking its consumer list, so they can not change.
if cfg.Direct != ncfg.Direct {
return errors.New("direct can not be updated")
}
if cfg.Sourcing != ncfg.Sourcing {
return errors.New("sourcing can not be updated")
}
if cfg.OptStartSeq != ncfg.OptStartSeq {
return errors.New("start sequence can not be updated")
}
if cfg.OptStartTime != nil && ncfg.OptStartTime != nil {
// Both have start times set, compare them directly:
if !cfg.OptStartTime.Equal(*ncfg.OptStartTime) {
return errors.New("start time can not be updated")
}
} else if cfg.OptStartTime != nil || ncfg.OptStartTime != nil {View on GitHub (pinned to 3a66a489d2)
Solutions
- Delete and recreate the consumer with the desired storage type.
- Keep the existing storage type in the update payload.
- Use a new durable name with the desired storage and cut over.
- Standardize storage settings in templates so env-specific diffs don't flip this field.
Example fix
// before
js.UpdateConsumer(stream, &nats.ConsumerConfig{Durable: "worker", MemoryStorage: true})
// after
js.DeleteConsumer(stream, "worker")
js.AddConsumer(stream, &nats.ConsumerConfig{Durable: "worker", MemoryStorage: true}) Defensive patterns
Strategy: validation
Validate before calling
if existing.MemoryStorage != desired.MemoryStorage {
return errors.New("storage type cannot be updated; recreate the consumer")
} Prevention
- Pin storage type centrally, not per environment template
- Echo the existing MemoryStorage value back in update payloads
- Recreate consumers when storage requirements change
When it happens
Trigger: js.UpdateConsumer (or CONSUMER.CREATE on an existing durable) where cfg.MemoryStorage differs from ncfg.MemoryStorage — e.g. created with FileStorage but update passes MemoryStorage: true (or vice versa).
Common situations: Switching consumers to memory for performance after rollout; environment-specific templates toggling storage; recreating a durable from an infra-as-code diff that changed the storage flag.
Related errors
- deliver policy can not be updated
- direct can not be updated
- sourcing can not be updated
- start sequence can not be updated
- start time can not be updated
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/ef776b2407574f08.
Report an issue: GitHub.