nats-io/nats-server · error
config reload does not support moving to or from an account
Error message
config reload does not support moving to or from an account resolver
What it means
In nats-server, `gnatsd --signal reload` (or SIGHUP) re-processes the config file and diffs it against the running options. The `accounts` block supports hot reload only if the account resolver configuration stays in place: you cannot add or remove a resolver (the embedded resolver or an external HTTP resolver) at runtime. When the diff detects oldValue==nil XOR newValue==nil for the resolver option, ProcessReloadError returns this error and the whole reload is rejected.
Source
Thrown at server/reload.go:1750
diffOpts = append(diffOpts, &maxPingsOutOption{newValue: newValue.(int)})
case "writedeadline":
diffOpts = append(diffOpts, &writeDeadlineOption{newValue: newValue.(time.Duration)})
case "clientadvertise":
cliAdv := newValue.(string)
if cliAdv != "" {
// Validate ClientAdvertise syntax
if _, _, err := parseHostPort(cliAdv, 0); err != nil {
return nil, fmt.Errorf("invalid ClientAdvertise value of %s, err=%v", cliAdv, err)
}
}
diffOpts = append(diffOpts, &clientAdvertiseOption{newValue: cliAdv})
case "accounts":
diffOpts = append(diffOpts, &accountsOption{})
case "resolver", "accountresolver", "accountsresolver":
// We can't move from no resolver to one. So check for that.
if (oldValue == nil && newValue != nil) ||
(oldValue != nil && newValue == nil) {
return nil, fmt.Errorf("config reload does not support moving to or from an account resolver")
}
diffOpts = append(diffOpts, &accountsOption{})
case "accountresolvertlsconfig":
diffOpts = append(diffOpts, &accountsOption{})
case "gateway":
// Not supported for now, but report warning if configuration of gateway
// is actually changed so that user knows that it won't take effect.
// Any deep-equal is likely to fail for when there is a TLSConfig. so
// remove for the test.
tmpOld := oldValue.(GatewayOpts)
tmpNew := newValue.(GatewayOpts)
tmpOld.TLSConfig = nil
tmpNew.TLSConfig = nil
tmpOld.tlsConfigOpts = nil
tmpNew.tlsConfigOpts = nil
// Allow TLSPinnedCerts through reload, existing connectionsView on GitHub (pinned to 3a66a489d2)
Solutions
- Restart the server instead of reloading when the presence of the account resolver changes
- Make the reload a no-op by keeping the resolver key identical in old and new configs and only changing other account fields
- Plan a deliberate restart/migration window to add or remove the resolver
Example fix
// before (config had no resolver, reload adds one)
accounts: { APP: { users: [app] }, resolver: MEMORY }
// after (either keep resolver present on both sides before reloading,
// or restart the server instead of signaling reload)
server # restart, e.g. systemctl restart nats-server Defensive patterns
Strategy: validation
Validate before calling
// Before signaling reload, compare resolver presence:
func resolverPresenceChanged(old, new *Options) bool {
return (old.AccountResolver == nil) != (new.AccountResolver == nil)
}
// if resolverPresenceChanged(old, new) { restartInsteadOfReload() } Type guard
func hasResolver(o *Options) bool { return o != nil && o.AccountResolver != nil } Prevention
- Never add or remove the accounts resolver via SIGHUP; treat resolver presence as a restart-only change
- Diff old and new configs in CI and fail if the resolver key appears/disappears
- Template configs so the resolver key is always present (even if unchanged) once adopted
When it happens
Trigger: Sending a reload signal after adding an `resolver: URL` or `resolver: MEMORY` key to the `accounts` block of a config that previously had none, or removing the resolver key (or the accounts resolver TLS config changing presence) from a config that had one.
Common situations: Operators moving a cluster from static account definitions to a JWT/account-resolution setup (or back) by editing the config and issuing SIGHUP; infra-as-code tools that rewrite the accounts block and inadvertently drop or add the resolver field; switching between embedded and HTTP resolvers in a rolling config update.
Related errors
- config reload not supported for %s: old=%v, new=%v
- config reload not supported for %s: %v
- config reload not supported for jetstream storage directory
- config reload not supported for jetstream dynamic max memory
- config reload not supported for decreasing jetstream max mem
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/614fc1082da079fc.
Report an issue: GitHub.