nats-io/nats-server · error
operators require an account resolver to be configured
Error message
operators require an account resolver to be configured
What it means
This error is thrown by validateTrustedOperators in server/jwt.go when operator-mode (TrustedOperators) is configured but no AccountResolver is set. Operator mode relies on decentralized JWT authentication, so the server needs a resolver (memory, directory, or NATS-based) to look up account signing keys and account JWTs. Without it, operator mode cannot function, so server startup is aborted.
Source
Thrown at server/jwt.go:92
return fmt.Errorf("default sentinel requires operators and accounts")
}
return nil
}
if o.DefaultSentinel != _EMPTY_ {
juc, err := jwt.DecodeUserClaims(o.DefaultSentinel)
if err != nil {
return fmt.Errorf("default sentinel JWT not valid")
}
if !juc.BearerToken && juc.IssuerAccount != "" && juc.HasEmptyPermissions() {
// we cannot resolve the account yet - but this looks like a scoped user
// it will be rejected at runtime if not valid
} else if !juc.BearerToken {
return fmt.Errorf("default sentinel must be a bearer token")
}
}
if o.AccountResolver == nil {
return fmt.Errorf("operators require an account resolver to be configured")
}
if len(o.Accounts) > 0 {
return fmt.Errorf("operators do not allow Accounts to be configured directly")
}
if len(o.Users) > 0 || len(o.Nkeys) > 0 {
return fmt.Errorf("operators do not allow users to be configured directly")
}
if len(o.TrustedOperators) > 0 && len(o.TrustedKeys) > 0 {
return fmt.Errorf("conflicting options for 'TrustedKeys' and 'TrustedOperators'")
}
if o.SystemAccount != _EMPTY_ {
foundSys := false
foundNonEmpty := false
for _, op := range o.TrustedOperators {
if op.SystemAccount != _EMPTY_ {
foundNonEmpty = true
}
if op.SystemAccount == o.SystemAccount {View on GitHub (pinned to 3a66a489d2)
Solutions
- Add a resolver to the config, e.g. `resolver: MEMORY` with `include accounts/` directives, or `resolver: URL(nats://resolver-host:4222)` for a NATS-based resolver
- If you only need static accounts, drop the operator setting and configure accounts/users directly instead of operator mode
- Verify with `nats-server -c nats.conf -t` (config test) before deploying
Example fix
// before
operator: eyJhbGciOi...
// after
operator: eyJhbGciOi...
resolver: MEMORY
resolver_preload: {
AD...: eyJhbGciOi...
} Defensive patterns
Strategy: validation
Validate before calling
// Go: check options before ProcessOptions/ValidateOptions
if len(o.TrustedOperators) > 0 && o.AccountResolver == nil {
return fmt.Errorf("config sets operators but no resolver")
} Prevention
- Always pair an `operator:` line with a `resolver:` line in configs
- Run `nats-server -c file.conf -t` in CI to validate configs
- Keep a template operator config that includes resolver_preload
When it happens
Trigger: Config file sets an 'operator' (TrustedOperators) but omits any 'resolver' setting; validateOptions fails before the server starts.
Common situations: Minimal operator-mode configs copied from docs that show the operator JWT but forget the resolver: e.g. `operator: <jwt>` with no `resolver: MEMORY` or `resolver: URL(...)` line; also when switching from plain account config to operator mode and deleting the resolver block.
Related errors
- operators do not allow Accounts to be configured directly
- operators do not allow users to be configured directly
- conflicting options for 'TrustedKeys' and 'TrustedOperators'
- system_account in config and operator JWT must be identical
- operator %s expects version %s got error instead: %s
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/666a25d478d5591f.
Report an issue: GitHub.