{"record":{"id":"614fc1082da079fc","repo":"nats-io/nats-server","slug":"config-reload-does-not-support-moving-to-or-from-a","errorCode":null,"errorMessage":"config reload does not support moving to or from an account resolver","messagePattern":"config reload does not support moving to or from an account resolver","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/reload.go","lineNumber":1750,"sourceCode":"\t\t\tdiffOpts = append(diffOpts, &maxPingsOutOption{newValue: newValue.(int)})\n\t\tcase \"writedeadline\":\n\t\t\tdiffOpts = append(diffOpts, &writeDeadlineOption{newValue: newValue.(time.Duration)})\n\t\tcase \"clientadvertise\":\n\t\t\tcliAdv := newValue.(string)\n\t\t\tif cliAdv != \"\" {\n\t\t\t\t// Validate ClientAdvertise syntax\n\t\t\t\tif _, _, err := parseHostPort(cliAdv, 0); err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"invalid ClientAdvertise value of %s, err=%v\", cliAdv, err)\n\t\t\t\t}\n\t\t\t}\n\t\t\tdiffOpts = append(diffOpts, &clientAdvertiseOption{newValue: cliAdv})\n\t\tcase \"accounts\":\n\t\t\tdiffOpts = append(diffOpts, &accountsOption{})\n\t\tcase \"resolver\", \"accountresolver\", \"accountsresolver\":\n\t\t\t// We can't move from no resolver to one. So check for that.\n\t\t\tif (oldValue == nil && newValue != nil) ||\n\t\t\t\t(oldValue != nil && newValue == nil) {\n\t\t\t\treturn nil, fmt.Errorf(\"config reload does not support moving to or from an account resolver\")\n\t\t\t}\n\t\t\tdiffOpts = append(diffOpts, &accountsOption{})\n\t\tcase \"accountresolvertlsconfig\":\n\t\t\tdiffOpts = append(diffOpts, &accountsOption{})\n\t\tcase \"gateway\":\n\t\t\t// Not supported for now, but report warning if configuration of gateway\n\t\t\t// is actually changed so that user knows that it won't take effect.\n\n\t\t\t// Any deep-equal is likely to fail for when there is a TLSConfig. so\n\t\t\t// remove for the test.\n\t\t\ttmpOld := oldValue.(GatewayOpts)\n\t\t\ttmpNew := newValue.(GatewayOpts)\n\t\t\ttmpOld.TLSConfig = nil\n\t\t\ttmpNew.TLSConfig = nil\n\t\t\ttmpOld.tlsConfigOpts = nil\n\t\t\ttmpNew.tlsConfigOpts = nil\n\n\t\t\t// Allow TLSPinnedCerts through reload, existing connections","sourceCodeStart":1732,"sourceCodeEnd":1768,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/reload.go#L1732-L1768","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (config had no resolver, reload adds one)\naccounts: { APP: { users: [app] }, resolver: MEMORY }\n// after (either keep resolver present on both sides before reloading,\n// or restart the server instead of signaling reload)\nserver # restart, e.g. systemctl restart nats-server","handlingStrategy":"validation","validationCode":"// Before signaling reload, compare resolver presence:\nfunc resolverPresenceChanged(old, new *Options) bool {\n\treturn (old.AccountResolver == nil) != (new.AccountResolver == nil)\n}\n// if resolverPresenceChanged(old, new) { restartInsteadOfReload() }","typeGuard":"func hasResolver(o *Options) bool { return o != nil && o.AccountResolver != nil }","tryCatchPattern":null,"preventionTips":["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"],"tags":["nats-server","config-reload","accounts-resolver"],"backgroundTag":"unsupported-hot-reload","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}