nats-io/nats-server · error

config reload not supported for jetstream storage directory

Error message

config reload not supported for jetstream storage directory

What it means

JetStream's storage directory (`store_dir`) cannot be changed while JetStream is enabled and running. During config reload, if the jetstream block was modified and the new store_dir is non-empty and different, the server rejects the reload because moving live stream/metadata storage at runtime is not supported. An empty new store_dir is tolerated because it means JetStream is being disabled or using a temp dir, which is checked later.

Source

Thrown at server/reload.go:1820

			if new != old {
				diffOpts = append(diffOpts, &jetStreamOption{newValue: new})
			}

			// Mark whether JS will be disabled.
			disableJS = !new
		case "storedir":
			new := newValue.(string)
			old := oldValue.(string)
			modified := new != old

			// Check whether JS is being disabled and/or storage dir attempted to change.
			if jsEnabled && modified {
				if new == _EMPTY_ {
					// This means that either JS is being disabled or it is using an temp dir.
					// Allow the change but error in case JS was not disabled.
					jsStoreDirChanged = true
				} else {
					return nil, fmt.Errorf("config reload not supported for jetstream storage directory")
				}
			}
		case "jetstreammaxmemory", "jetstreammaxstore":
			old := oldValue.(int64)
			new := newValue.(int64)

			// Check whether JS is being disabled and/or limits are being changed.
			var (
				modified  = new != old
				fromUnset = old == -1
				fromSet   = !fromUnset
				toUnset   = new == -1
				toSet     = !toUnset
				increased = fromSet && toSet && new > old
			)
			if jsEnabled && modified {
				// Cannot change limits from dynamic storage at runtime.
				switch {

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Keep `jetstream.store_dir` unchanged across reloads; leave it empty to use the default
  2. To relocate storage, disable JetStream or stop the server, move the data directory, update the config, and restart
  3. If the new value is empty (temp/disabled), the reload proceeds — verify JS is actually being disabled or you'll hit a later error

Example fix

// before
jetstream { store_dir: "/data/new-path" }  # + reload signal
// after
server # systemctl stop nats-server && mv /data/old-path/* /data/new-path/
jetstream { store_dir: "/data/new-path" }
server # systemctl start nats-server
Defensive patterns

Strategy: validation

Validate before calling

// Refuse to reload when store_dir changes while JS stays enabled:
func storeDirChanged(old, new *Options) bool {
	return old.JetStream && new.JetStream &&
		old.StoreDir != new.StoreDir && new.StoreDir != ""
}
// if storeDirChanged(old, new) { scheduleRestart() }

Prevention

When it happens

Trigger: SIGHUP reload after editing `jetstream.store_dir` to a different non-empty path while JetStream is enabled; moving storage to a bigger disk by editing the config and reloading instead of restarting.

Common situations: Operators migrating JetStream data to a new volume via config edit + reload; automation tools normalizing store_dir paths; changing store_dir from an explicit path back to a different explicit default.

Related errors


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