nats-io/nats-server · error
error non operator mode account %q: attempted to use issuer_
Error message
error non operator mode account %q: attempted to use issuer_account
What it means
In non-operator mode, the auth callout response's user JWT set an IssuerAccount, which is illegal: it would let the callout effectively issue users on a different account. The server rejects the response outright. IssuerAccount is only meaningful in operator (decentralized JWT) mode.
Source
Thrown at server/auth_callout.go:175
// only in operator mode we expect to receive `issuer_account`.
getIssuerAccount := func(arc *jwt.UserClaims, account string) (string, error) {
// Make sure correct issuer.
var issuer string
if opts.AuthCallout != nil {
issuer = opts.AuthCallout.Issuer
} else {
// Operator mode is who we send the request on unless switching accounts.
issuer = acc.Name
}
// the jwt issuer can be a signing key
jwtIssuer := arc.Issuer
if arc.IssuerAccount != _EMPTY_ {
if !isOperatorMode {
// this should be invalid - effectively it would allow the auth callout
// to issue on another account which may be allowed given the configuration
// where the auth callout account can handle multiple different ones..
return _EMPTY_, fmt.Errorf("error non operator mode account %q: attempted to use issuer_account", account)
}
jwtIssuer = arc.IssuerAccount
}
if jwtIssuer != issuer {
if !isOperatorMode {
return _EMPTY_, fmt.Errorf("wrong issuer for auth callout response on account %q, expected %q got %q", account, issuer, jwtIssuer)
} else if !acc.isAllowedAcount(jwtIssuer) {
return _EMPTY_, fmt.Errorf("account %q not permitted as valid account option for auth callout for account %q",
arc.Issuer, account)
}
}
return jwtIssuer, nil
}
getExpirationAndAllowedConnections := func(arc *jwt.UserClaims, account string) (time.Duration, map[string]struct{}, error) {
allowNow, expiration := validateTimes(arc)
if !allowNow {View on GitHub (pinned to 3a66a489d2)
Solutions
- Remove IssuerAccount from the claims the callout emits; rely on Issuer only.
- If per-account issuing is needed, run the deployment in operator mode with a proper account JWT.
- Verify the server's mode (operator vs local) matches what the callout service assumes.
Example fix
// before arc.IssuerAccount = calloutAccountPub // after arc.IssuerAccount = _EMPTY_ // not allowed in non-operator mode arc.Issuer = calloutAccountPub
Defensive patterns
Strategy: validation
Validate before calling
if arc.IssuerAccount != "" && !operatorMode {
return errors.New("issuer_account not permitted in non-operator mode")
} Prevention
- Never set IssuerAccount unless running in operator mode.
- Share claim-building code conditionally on deployment mode.
- Add a pre-publish Validate check in the callout for this field.
When it happens
Trigger: A callout service builds AuthorizationResponseClaims/UserClaims with IssuerAccount populated while the server runs without an operator (account/server-local auth callout), then the user connects.
Common situations: Reusing callout code written for operator-mode deployments in a plain server setup; blindly copying example configs that set IssuerAccount.
Related errors
- operators do not allow authorization callouts to be configur
- account %q not permitted as valid account option for auth ca
- authorization response had validation errors: %v
- wrong issuer for auth callout response on account %q, expect
- authorized user on account %q outside of valid connect times
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/e727436e56353c3e.
Report an issue: GitHub.