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

  1. Delete and recreate the consumer with the desired OptStartTime.
  2. Keep OptStartTime identical (same instant) in update requests.
  3. Freeze the start-time value in config management instead of computing it at deploy time.
  4. 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

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


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/dc66df3b4da9714c. Report an issue: GitHub.