nats-io/nats-server · error

conflicting options for 'TrustedKeys' and 'TrustedOperators'

Error message

conflicting options for 'TrustedKeys' and 'TrustedOperators'

What it means

A config may specify trust either via the legacy `trusted` keys list (TrustedKeys) or via `operator` entries (TrustedOperators), not both. This error is thrown when both are present, since the effective trust anchors would be ambiguous.

Source

Thrown at server/jwt.go:101

		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 {
				foundSys = true
				break
			}
		}
		if foundNonEmpty && !foundSys {
			return fmt.Errorf("system_account in config and operator JWT must be identical")
		}
	} else if o.TrustedOperators[0].SystemAccount == _EMPTY_ {
		// In case the system account is neither defined in config nor in the first operator.

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Remove the `trusted:` keys line and rely solely on operator JWTs (preferred)
  2. Or remove the `operator:` line if you still want raw trusted-key mode

Example fix

// before
trusted: [OAF...]
operator: eyJ...
// after
operator: eyJ...
Defensive patterns

Strategy: validation

Validate before calling

// Go: detect dual trust anchors
if len(o.TrustedOperators) > 0 && len(o.TrustedKeys) > 0 {
    return fmt.Errorf("choose either trusted keys or operators")
}

Prevention

When it happens

Trigger: Config sets both `operator: [...]` and `trusted: [keys...]`; validateOptions fails at startup.

Common situations: Upgrading from trusted-keys configs to operator JWTs and leaving the `trusted:` line behind; adding an operator JWT to an existing trusted-keys server.

Related errors


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