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

  1. Regenerate the account claim JWT with the correct signing key (the operator or designated account issuer) using nsc
  2. Validate the JWT offline (nsc describe / jwt decoder) before pushing the update
  3. Ensure the claim's issuer matches the account's expected signer and the account subject (sub) matches the account being updated
  4. 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

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


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