{"record":{"id":"bc59f06760f7b9d8","repo":"SigNoz/signoz","slug":"api-key-expired","errorCode":"api_key_expired","errorMessage":"api key has been expired","messagePattern":"api key has been expired","errorType":"error_code","errorClass":null,"httpStatus":401,"severity":"error","filePath":"pkg/types/serviceaccounttypes/factor_api_key.go","lineNumber":101,"sourceCode":"\t\t},\n\t\tKey: key,\n\t}\n}\n\nfunc (apiKey *FactorAPIKey) Update(name string, expiresAt uint64) error {\n\tapiKey.Name = name\n\tapiKey.ExpiresAt = expiresAt\n\tapiKey.UpdatedAt = time.Now()\n\treturn nil\n}\n\nfunc (apiKey *FactorAPIKey) IsExpired() error {\n\tif apiKey.ExpiresAt == 0 {\n\t\treturn nil\n\t}\n\n\tif time.Now().After(time.Unix(int64(apiKey.ExpiresAt), 0)) {\n\t\treturn errors.New(errors.TypeUnauthenticated, ErrCodeAPIKeyExpired, \"api key has been expired\")\n\t}\n\n\treturn nil\n}\n\nfunc (key *PostableFactorAPIKey) UnmarshalJSON(data []byte) error {\n\ttype Alias PostableFactorAPIKey\n\n\tvar temp Alias\n\tif err := json.Unmarshal(data, &temp); err != nil {\n\t\treturn err\n\t}\n\n\tif match := factorAPIKeyNameRegex.MatchString(temp.Name); !match {\n\t\treturn errInvalidAPIKeyName\n\t}\n\n\tif temp.ExpiresAt != 0 && time.Now().After(time.Unix(int64(temp.ExpiresAt), 0)) {","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/SigNoz/signoz/blob/5069bf80b08f1f00d7e014eccc09902f9871004f/pkg/types/serviceaccounttypes/factor_api_key.go#L83-L119","documentation":"FactorAPIKey.IsExpired returns this error (type Unauthenticated) when the current time is past the key's ExpiresAt unix timestamp. A zero ExpiresAt means the key never expires and returns nil. Callers treat this as authentication failure.","triggerScenarios":"Authenticating with an API key whose expires_at timestamp is in the past — any request using that key for auth is rejected as unauthenticated.","commonSituations":"Keys created with short TTLs for testing left in configs; expired keys after rotation policies; clock drift where the server is ahead; long-lived CI jobs using aged keys.","solutions":["Generate a new API key and update the credential in your config/env","If keys should not expire, create them with no expiry (ExpiresAt=0)","Set up rotation before expiry with reminders at 80% TTL","Check server clock skew if you believe the key is still valid"],"exampleFix":"// before\nSIGNOZ_API_KEY=expired-key-01HX...\n# after (rotate)\nsignoz api-key create --name ci-key --expires-in 720h\nSIGNOZ_API_KEY=<new-key>\n","handlingStrategy":"try-catch","validationCode":"const exp = key.expires_at; // unix seconds\nif (exp && Date.now()/1000 > exp) throw new Error('rotate key: expired');","typeGuard":"function keyUsable(k: {expires_at:number}): boolean { return !k.expires_at || Date.now()/1000 < k.expires_at; }","tryCatchPattern":"if err := apiKey.IsExpired(); err != nil { rotateKey(); retry request with new key }","preventionTips":["Automate rotation before expiry","Store ExpiresAt with the credential and warn at 80% TTL"],"tags":["api-key","authentication","expiry","go"],"backgroundTag":"api-key-expired","analyzedSha":"5069bf80b08f1f00d7e014eccc09902f9871004f","analyzedAt":"2026-08-28T06:22:12.824Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}