nats-io/nats-server · error
start time can not be updated
Error message
start time can not be updated
What it means
When both the existing and the proposed configs have OptStartTime set but the times differ, the start time is considered changed and rejected — OptStartTime cannot be updated after creation. checkNewConsumerConfig compares them with time.Equal and returns this error on mismatch.
Source
Thrown at server/consumer.go:2554
}
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 {
// At least one start time is set and the other is not
return errors.New("start time can not be updated")
}
if cfg.AckPolicy != ncfg.AckPolicy {
return errors.New("ack policy can not be updated")
}
if cfg.ReplayPolicy != ncfg.ReplayPolicy {
return errors.New("replay policy can not be updated")
}
if cfg.Heartbeat != ncfg.Heartbeat {
return errors.New("heart beats can not be updated")
}
if cfg.FlowControl != ncfg.FlowControl {
return errors.New("flow control can not be updated")
}
View on GitHub (pinned to 3a66a489d2)
Solutions
- Delete and recreate the consumer with the desired OptStartTime.
- Keep OptStartTime identical (same instant) in update requests.
- Freeze the start-time value in config management instead of computing it at deploy time.
- Normalize timestamps (UTC, consistent precision) before comparing/sending.
Example fix
// before
js.UpdateConsumer(stream, &nats.ConsumerConfig{Durable: "replay", OptStartTime: &newTime})
// after
js.DeleteConsumer(stream, "replay")
js.AddConsumer(stream, &nats.ConsumerConfig{Durable: "replay", OptStartTime: &newTime}) Defensive patterns
Strategy: validation
Validate before calling
if existing.OptStartTime != nil && desired.OptStartTime != nil && !existing.OptStartTime.Equal(*desired.OptStartTime) {
return errors.New("start time cannot be updated; recreate the consumer")
} Prevention
- Store the original start time and reuse it verbatim in updates
- Normalize timestamps to UTC with fixed precision
- Compute time-based starts only at consumer creation
When it happens
Trigger: js.UpdateConsumer on an existing durable created with DeliverByStartTime where the update passes a different OptStartTime timestamp (even a slightly different value for the same intended moment).
Common situations: Replaying from 'yesterday' instead of the original start date; regenerating configs from templates where the computed timestamp shifts each run; timezone or precision differences (RFC3339 with/without fractional seconds) causing inequality.
Related errors
- deliver policy can not be updated
- storage type can not be updated
- direct can not be updated
- sourcing can not be updated
- start sequence can not be updated
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/dc66df3b4da9714c.
Report an issue: GitHub.