nats-io/nats-server · error
account validation failed
Error message
account validation failed
What it means
ErrAccountValidation is returned when an account has failed validation — typically when an updated account claim JWT fails decoding/validation (bad signature, issuer mismatch, invalid revocations, etc.) during updateAccountWithClaimJWT or account claim updates. The server rejects the update and keeps the previous account state.
Source
Thrown at server/errors.go:123
ErrBadAccount = errors.New("bad account")
// ErrReservedAccount represents a reserved account that can not be created.
ErrReservedAccount = errors.New("reserved account")
// ErrMissingAccount is returned when an account does not exist.
ErrMissingAccount = errors.New("account missing")
// ErrMissingService is returned when an account does not have an exported service.
ErrMissingService = errors.New("service missing")
// ErrBadServiceType is returned when latency tracking is being applied to non-singleton response types.
ErrBadServiceType = errors.New("bad service response type")
// ErrBadSampling is returned when the sampling for latency tracking is not 1 >= sample <= 100.
ErrBadSampling = errors.New("bad sampling percentage, should be 1-100")
// ErrAccountValidation is returned when an account has failed validation.
ErrAccountValidation = errors.New("account validation failed")
// ErrAccountExpired is returned when an account has expired.
ErrAccountExpired = errors.New("account expired")
// ErrNoAccountResolver is returned when we attempt an update but do not have an account resolver.
ErrNoAccountResolver = errors.New("account resolver missing")
// ErrAccountResolverUpdateTooSoon is returned when we attempt an update too soon to last request.
ErrAccountResolverUpdateTooSoon = errors.New("account resolver update too soon")
// ErrAccountResolverSameClaims is returned when same claims have been fetched.
ErrAccountResolverSameClaims = errors.New("account resolver no new claims")
// ErrStreamImportAuthorization is returned when a stream import is not authorized.
ErrStreamImportAuthorization = errors.New("stream import not authorized")
// ErrStreamImportBadPrefix is returned when a stream import prefix contains wildcards.
ErrStreamImportBadPrefix = errors.New("stream import prefix can not contain wildcard tokens")View on GitHub (pinned to 3a66a489d2)
Solutions
- Regenerate the account claim JWT with the correct signing key (the operator or designated account issuer) using nsc
- Validate the JWT offline (nsc describe / jwt decoder) before pushing the update
- Ensure the claim's issuer matches the account's expected signer and the account subject (sub) matches the account being updated
- Remove or fix invalid claim fields (imports/exports/limits/revocations) and retry the update
Example fix
// before jwt2, _ := issuesigned(ajwt2, badKey) // signed with wrong issuer err := sa.updateAccountWithClaimJWT(acc, jwt2) // ErrAccountValidation // after jwt2, _ := issuesigned(ajwt2, operatorKey) // correct issuer err := sa.updateAccountWithClaimJWT(acc, jwt2)
Defensive patterns
Strategy: try-catch
Validate before calling
// validate the claim JWT offline before pushing it
c, err := jwt.DecodeAccountClaims(jwtStr)
if err != nil || c.Subject != accountPubKey || !signedByTrustedIssuer(jwtStr) { return errors.New("claim will fail validation") } Type guard
func validAccountClaim(jwtStr, accountPub string) bool {
c, err := jwt.DecodeAccountClaims(jwtStr)
return err == nil && c != nil && c.Subject == accountPub
} Try / catch
if err := srv.UpdateAccountClaim(acc, ajwt); err != nil {
if errors.Is(err, ErrAccountValidation) { /* re-sign claim with correct issuer and retry */ }
} Prevention
- Sign account claims with the correct operator/account issuer key
- Validate claims with nsc/jwt library before pushing updates
- Keep issuer account and claim subject consistent after key rotation
When it happens
Trigger: Calling Server.updateAccountWithClaimJWT with a JWT whose claims fail validation; pushing an updated account claim via the system account $SYS.REQ.ACCOUNT.UPDATE endpoint where the new claim is invalid (e.g. signed by an account that is not the claim issuer, wrong issuer account, expired or tampered claims); resolver-driven updates with invalid claims.
Common situations: Signing account updates with the wrong operator/account key after rotating credentials; nsc-generated claims edited by hand; mismatched issuer accounts in multi-operator setups; updating a claim with permissions that violate validation rules (e.g. bad imports/exports). Tests like TestBadAccountUpdate and the events_test.go:907 flow exercise exactly this path.
Related errors
- account expired
- account jwt not found
- auth callout violation: auth callout response is not for exp
- auth callout violation: auth callout response is not for ser
- auth callout signing key is unknown
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/87d9d2185b0c1bd7.
Report an issue: GitHub.