nats-io/nats-server · error

unable to add account %q to the list of dedicated routes: %v

Error message

unable to add account %q to the list of dedicated routes: %v

What it means

During cluster options reload, newly added dedicated-reserve/pool accounts (co.accsAdded) are validated with s.LookupAccount. If an added account cannot be resolved, reload fails, wrapping the lookup error, because routes require the account to exist.

Source

Thrown at server/reload.go:1704

		case "nkeys":
			diffOpts = append(diffOpts, &nkeysOption{})
		case "cluster":
			newClusterOpts := newValue.(ClusterOpts)
			oldClusterOpts := oldValue.(ClusterOpts)
			if err := validateClusterOpts(oldClusterOpts, newClusterOpts); err != nil {
				return nil, err
			}
			co := &clusterOption{
				newValue:        newClusterOpts,
				permsChanged:    !reflect.DeepEqual(newClusterOpts.Permissions, oldClusterOpts.Permissions),
				compressChanged: !oldClusterOpts.Compression.equals(&newClusterOpts.Compression),
			}
			co.diffPoolAndAccounts(&oldClusterOpts)
			// If there are added accounts, first make sure that we can look them up.
			// If we can't let's fail the reload.
			for _, acc := range co.accsAdded {
				if _, err := s.LookupAccount(acc); err != nil {
					return nil, fmt.Errorf("unable to add account %q to the list of dedicated routes: %v", acc, err)
				}
			}
			// If pool_size has been set to negative (but was not before), then let's
			// add the system account to the list of removed accounts (we don't have
			// to check if already there, duplicates are ok in that case).
			if newClusterOpts.PoolSize < 0 && oldClusterOpts.PoolSize >= 0 {
				if sys := s.SystemAccount(); sys != nil {
					co.accsRemoved = append(co.accsRemoved, sys.GetName())
				}
			}
			diffOpts = append(diffOpts, co)
		case "routes":
			add, remove := diffRoutes(oldValue.([]*url.URL), newValue.([]*url.URL))
			diffOpts = append(diffOpts, &routesOption{add: add, remove: remove})
		case "maxconn":
			diffOpts = append(diffOpts, &maxConnOption{newValue: newValue.(int)})
		case "pidfile":
			diffOpts = append(diffOpts, &pidFileOption{newValue: newValue.(string)})

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Define the referenced accounts in the accounts{} block (or resolver) so LookupAccount succeeds, then reload again.
  2. Fix the account name typo in the cluster dedicated accounts list.
  3. Check resolver setup (memory resolver payload / URL resolver) includes the new accounts and the resolver is reachable.
  4. Revert the pool/account change if the accounts cannot be provisioned yet.

Example fix

// before
cluster { pool_size: 2 } // account "missing_acc" not defined
// after
accounts { missing_acc { users: [...] } }
cluster { pool_size: 2 }
Defensive patterns

Strategy: validation

Validate before calling

for _, accName := range newClusterDedicatedAccounts {
    if _, err := srv.LookupAccount(accName); err != nil {
        return fmt.Errorf("account %q must be defined before reload", accName)
    }
}

Try / catch

if err := srv.Reload(); err != nil {
    if strings.Contains(err.Error(), "dedicated routes") {
        log.Printf("add missing accounts and reload again: %v", err)
    }
}

Prevention

When it happens

Trigger: cluster.pool_size / dedicated cluster accounts changed so that new accounts are added, but LookupAccount(name) fails — the account is not defined or not yet resolvable (no resolver hit, or listed only in the new config's removed/added sets inconsistently).

Common situations: Setting cluster { pool_size: -N } with accounts not defined in `accounts{}`; misspelled account names in cluster resolvers; memory resolver config missing the referenced account.

Related errors


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