{"record":{"id":"efbacd2fcf8cdd66","repo":"nats-io/nats-server","slug":"account-expired","errorCode":null,"errorMessage":"account expired","messagePattern":"account expired","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/errors.go","lineNumber":126,"sourceCode":"\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\")\n\n\t// ErrStreamImportDuplicate is returned when a stream import is a duplicate of one that already exists.\n\tErrStreamImportDuplicate = errors.New(\"stream import already exists\")","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/errors.go#L108-L144","documentation":"ErrAccountExpired is returned when an account has expired — its claims contain an expiry that has passed, so the server refuses to resolve or use the account. LookupAccount and related resolution paths surface it, and monitoring endpoints check for it (including err==nil with acc.IsExpired()).","triggerScenarios":"LookupAccount on an account whose JWT exp claim is in the past; account resolver fetching an expired claim; monitor account-stats endpoints requesting an expired account (monitor.go:3747); JetStream flows checking errors.Is(err, ErrAccountExpired) (jetstream_jwt_test.go:1182).","commonSituations":"Operator-issued account credentials past their expiration date in long-lived deployments; test/dev accounts issued with short TTLs; system clock skew making a valid claim appear expired; forgetting to renew account JWTs in a resolver setup.","solutions":["Re-issue or renew the account JWT with a later/longer expiry (nsc update or push a new claim via $SYS.REQ.CLAIM.UPDATE)","Push the renewed claim to the account resolver so lookups succeed","Check system clock (NTP) if expiry appears to have passed prematurely","If intentionally testing expiry handling, expect and match this error rather than treating it as fatal"],"exampleFix":"// before\nacc, err := s.LookupAccount(apub) // claim exp passed -> ErrAccountExpired\n// after\nnewJWT := renewAccountJWT(apub, 24*time.Hour) // re-sign with future exp\npushClaimToResolver(newJWT)\nacc, err := s.LookupAccount(apub)","handlingStrategy":"type-guard","validationCode":"c, err := jwt.DecodeAccountClaims(accJWT)\nif err == nil && c.ClaimsData.Expiration > 0 && c.ClaimsData.Expiration <= time.Now().Unix() { return errors.New(\"account claim already expired\") }","typeGuard":"func isAccountExpiredErr(err error) bool { return errors.Is(err, ErrAccountExpired) }\nfunc accountIsExpired(acc *Account) bool { return acc != nil && acc.IsExpired() }","tryCatchPattern":"acc, err := s.LookupAccount(apub)\nif isAccountExpiredErr(err) { renewAccountJWT(apub); return } // handle expiry gracefully","preventionTips":["Renew account JWTs before expiry (monitor exp with alerts)","Use NTP to keep server clocks accurate","Prefer long-lived claims in production; short TTLs only for tests"],"tags":["nats","server","jwt","account-expiry"],"backgroundTag":"jwt-token-expired","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}