nats-io/nats-server · error

validation errors: %v

Error message

validation errors: %v

What it means

claimValidate validates an *jwt.AccountClaims using the nkeys/jwt library's ValidationResults. If any blocking validation errors are found (expired/invalid dates, bad subject/public key pairing, malformed limits, etc.), the server wraps all of them in 'validation errors: %v' and rejects the account claim update.

Source

Thrown at server/accounts.go:4436

		strict = opts.TrustedOperators[0].StrictSigningKeyUsage
		if !strict {
			keys[opts.TrustedOperators[0].Subject] = struct{}{}
		}
		for _, key := range opts.TrustedOperators[0].SigningKeys {
			keys[key] = struct{}{}
		}
	}
	if len(keys) == 0 {
		return _EMPTY_, nil, false, fmt.Errorf("no operator key found")
	}
	return op, keys, strict, nil
}

func claimValidate(claim *jwt.AccountClaims) error {
	vr := &jwt.ValidationResults{}
	claim.Validate(vr)
	if vr.IsBlocking(false) {
		return fmt.Errorf("validation errors: %v", vr.Errors())
	}
	return nil
}

func removeCb(s *Server, pubKey string) {
	v, ok := s.accounts.Load(pubKey)
	if !ok {
		return
	}
	a := v.(*Account)
	s.Debugf("Disable account %s due to remove", pubKey)
	a.mu.Lock()
	// lock out new clients
	a.msubs = 0
	a.mpay = 0
	a.mconns = 0
	a.mleafs = 0
	a.updated = time.Now()

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Read the %v list in the error — it enumerates the exact validation failures — and fix the claim accordingly.
  2. Re-issue the account JWT with nsc (or current nats.go jwt package) and re-push it.
  3. Ensure server clock/NTP is correct and both nsc and nats-server are up to date.

Example fix

// before
claim.Expires = time.Now().Add(-time.Hour).Unix() // already expired
// after
claim.Expires = time.Now().Add(24 * time.Hour).Unix()
vr := &jwt.ValidationResults{}
claim.Validate(vr)
if vr.IsBlocking(false) { /* fix before publishing */ }
Defensive patterns

Strategy: validation

Validate before calling

vr := &jwt.ValidationResults{}
claim.Validate(vr)
if vr.IsBlocking(false) {
    return fmt.Errorf("claim invalid: %v", vr.Errors())
}

Try / catch

if err := pushAccountJWT(tok); err != nil && strings.Contains(err.Error(), "validation errors") {
    var vr jwt.ValidationResults
    fmt.Println(err) // enumerated causes: fix each, then re-push
}

Prevention

When it happens

Trigger: Publishing an account JWT whose claims fail jwt.AccountClaims.Validate with blocking results — expired token, subject not a valid account key, issuer mismatch, negative/invalid limits or imports/exports issues.

Common situations: Clock skew between the signing host and server; expired accounts after revocation/expiry windows; hand-edited JWTs; old nats-server versions not accepting newer claim fields; nsc/jwt library version mismatches.

Related errors


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