nats-io/nats-server · error

no valid account %q for auth callout response on account %q:

Error message

no valid account %q for auth callout response on account %q: %v

What it means

The server resolved which account the callout response's user belongs to (placement: cr.IssuerAccount in operator mode, otherwise the issuer) and called s.LookupAccount; that account does not exist locally, so the response cannot be applied. The wrapped %v carries the underlying lookup error (e.g. account not found).

Source

Thrown at server/auth_callout.go:227

		// Apply to this client.
		var err error
		issuerAccount, err := getIssuerAccount(arc, account)
		if err != nil {
			return nil, err
		}

		// if we are not in operator mode, they can specify placement as a tag
		var placement string
		if !isOperatorMode {
			// only allow placement if we are not in operator mode
			placement = arc.Audience
		} else {
			placement = issuerAccount
		}

		targetAcc, err := s.LookupAccount(placement)
		if err != nil {
			return nil, fmt.Errorf("no valid account %q for auth callout response on account %q: %v", placement, account, err)
		}
		if isOperatorMode {
			// this will validate the signing key that emitted the user, and if it is a signing
			// key it assigns the permissions from the target account
			if scope, ok := targetAcc.hasIssuer(arc.Issuer); !ok {
				return nil, fmt.Errorf("user JWT issuer %q is not known", arc.Issuer)
			} else if scope != nil {
				// this possibly has to be different because it could just be a plain issued by a non-scoped signing key
				if err := scope.ValidateScopedSigner(arc); err != nil {
					return nil, fmt.Errorf("user JWT is not valid: %v", err)
				} else if uSc, ok := scope.(*jwt.UserScope); !ok {
					return nil, fmt.Errorf("user JWT is not a valid scoped user")
				} else if arc.User.UserPermissionLimits, err = processUserPermissionsTemplate(uSc.Template, arc, targetAcc); err != nil {
					return nil, fmt.Errorf("user JWT generated invalid permissions: %v", err)
				}
			}
		}
		return targetAcc, nil

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Ensure the referenced account exists: push its account JWT to the resolver/operator account server.
  2. Fix the account public key configured in the callout service (check the quoted placement name in the error).
  3. Verify the callout's cr.IssuerAccount points to a real account on this server, not a key from another deployment.
  4. Trigger account lookup/refresh on the server (reconnect or nats account update) after pushing the JWT.

Example fix

// before
cr.IssuerAccount = "ABC...typo'd-key"
// after
cr.IssuerAccount = existingAccountPub // key present in the operator account list / resolver
Defensive patterns

Strategy: validation

Validate before calling

// callout side: ensure referenced account is known
if _, err := lookupAccount(cr.IssuerAccount); err != nil {
    return fmt.Errorf("response references unknown account %q", cr.IssuerAccount)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "no valid account") {
    // push/refresh the account JWT, then retry authorization
}

Prevention

When it happens

Trigger: The callout's AuthorizationResponseClaims references an account (via cr.IssuerAccount or issuer) that the server has not seen/loaded — LookupAccount returns an error — while processing an authorization response for the connecting user's account.

Common situations: Operator-mode deployments where the issuer account JWT was never pushed to the resolver; typo in the account public key configured in the callout; account deleted after the callout was configured.

Related errors


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