{"record":{"id":"87d9d2185b0c1bd7","repo":"nats-io/nats-server","slug":"account-validation-failed","errorCode":null,"errorMessage":"account validation failed","messagePattern":"account validation failed","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/errors.go","lineNumber":123,"sourceCode":"\tErrBadAccount = errors.New(\"bad account\")\n\n\t// ErrReservedAccount represents a reserved account that can not be created.\n\tErrReservedAccount = errors.New(\"reserved account\")\n\n\t// ErrMissingAccount is returned when an account does not exist.\n\tErrMissingAccount = errors.New(\"account missing\")\n\n\t// ErrMissingService is returned when an account does not have an exported service.\n\tErrMissingService = errors.New(\"service missing\")\n\n\t// ErrBadServiceType is returned when latency tracking is being applied to non-singleton response types.\n\tErrBadServiceType = errors.New(\"bad service response type\")\n\n\t// ErrBadSampling is returned when the sampling for latency tracking is not 1 >= sample <= 100.\n\tErrBadSampling = errors.New(\"bad sampling percentage, should be 1-100\")\n\n\t// ErrAccountValidation is returned when an account has failed validation.\n\tErrAccountValidation = errors.New(\"account validation failed\")\n\n\t// ErrAccountExpired is returned when an account has expired.\n\tErrAccountExpired = errors.New(\"account expired\")\n\n\t// ErrNoAccountResolver is returned when we attempt an update but do not have an account resolver.\n\tErrNoAccountResolver = errors.New(\"account resolver missing\")\n\n\t// ErrAccountResolverUpdateTooSoon is returned when we attempt an update too soon to last request.\n\tErrAccountResolverUpdateTooSoon = errors.New(\"account resolver update too soon\")\n\n\t// ErrAccountResolverSameClaims is returned when same claims have been fetched.\n\tErrAccountResolverSameClaims = errors.New(\"account resolver no new claims\")\n\n\t// ErrStreamImportAuthorization is returned when a stream import is not authorized.\n\tErrStreamImportAuthorization = errors.New(\"stream import not authorized\")\n\n\t// ErrStreamImportBadPrefix is returned when a stream import prefix contains wildcards.\n\tErrStreamImportBadPrefix = errors.New(\"stream import prefix can not contain wildcard tokens\")","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/errors.go#L105-L141","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\njwt2, _ := issuesigned(ajwt2, badKey) // signed with wrong issuer\nerr := sa.updateAccountWithClaimJWT(acc, jwt2) // ErrAccountValidation\n// after\njwt2, _ := issuesigned(ajwt2, operatorKey) // correct issuer\nerr := sa.updateAccountWithClaimJWT(acc, jwt2)","handlingStrategy":"try-catch","validationCode":"// validate the claim JWT offline before pushing it\nc, err := jwt.DecodeAccountClaims(jwtStr)\nif err != nil || c.Subject != accountPubKey || !signedByTrustedIssuer(jwtStr) { return errors.New(\"claim will fail validation\") }","typeGuard":"func validAccountClaim(jwtStr, accountPub string) bool {\n\tc, err := jwt.DecodeAccountClaims(jwtStr)\n\treturn err == nil && c != nil && c.Subject == accountPub\n}","tryCatchPattern":"if err := srv.UpdateAccountClaim(acc, ajwt); err != nil {\n\tif errors.Is(err, ErrAccountValidation) { /* re-sign claim with correct issuer and retry */ }\n}","preventionTips":["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"],"tags":["nats","server","jwt","account-validation"],"backgroundTag":"jwt-claim-validation-failed","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}