nats-io/nats-server · error
user JWT issuer %q is not known
Error message
user JWT issuer %q is not known
What it means
In operator mode, the server verified that the signing key that emitted the user JWT (arc.Issuer) is a known issuer on the target account via targetAcc.hasIssuer. The issuer is neither the account's identity key nor one of its signing keys, so the user JWT is rejected. Scoped signing keys are then validated further (see the following error).
Source
Thrown at server/auth_callout.go:233
// 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
}
processReply := func(_ *subscription, rc *client, racc *Account, subject, reply string, rmsg []byte) {
arc, err := decodeResponse(rc, rmsg, racc)
if err != nil {
c.authViolation()View on GitHub (pinned to 3a66a489d2)
Solutions
- Sign the user JWT with the target account's identity key or one of its configured signing keys.
- Add the key the callout uses to the target account JWT's signing keys list and re-push the account claim.
- Audit key rotation: reconfigure the callout after signing keys are rotated.
Example fix
// before signed, err := arc.Encode(oldSigningKey) // removed from account signing keys // after signed, err := arc.Encode(currentSigningKey) // listed in target account's signing_keys
Defensive patterns
Strategy: validation
Validate before calling
// callout side: confirm the signing key is one of the target account's issuers
if !accountSigningKeys.Contains(arc.Issuer) {
return fmt.Errorf("issuer %q is not a signing key of the target account", arc.Issuer)
} Prevention
- Sign user JWTs only with the target account's identity or listed signing keys.
- Update the callout immediately after account signing-key rotation.
- Store per-account signing keys explicitly in callout config.
When it happens
Trigger: Operator-mode auth callout emits a user JWT signed by a key that is not registered as an issuer/signing key of the resolved target account, so hasIssuer(arc.Issuer) returns ok=false.
Common situations: Signing with a key from a different account; account JWT updated and an old signing key removed while the callout still uses it; callout misconfigured with the wrong private key.
Related errors
- operators do not allow authorization callouts to be configur
- authorization response had validation errors: %v
- error non operator mode account %q: attempted to use issuer_
- wrong issuer for auth callout response on account %q, expect
- account %q not permitted as valid account option for auth ca
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/5c357c312352603b.
Report an issue: GitHub.