dromara/Sa-Token · error · ApiKeyException
12302
12302
Error message
API Key 已过期:
What it means
Thrown by SaApiKeyTemplate.checkApiKey(String) when the ApiKeyModel exists but ak.timeExpired() returns true — the key's expiresTime has passed. Code 12302 marks an expired key; the record is still present, only its validity window has elapsed.
Source
Thrown at sa-token-plugin/sa-token-apikey/src/main/java/cn/dev33/satoken/apikey/template/SaApiKeyTemplate.java:130
if(apiKeyModel == null) {
apiKeyModel = getApiKeyModelFromDatabase(apiKey);
saveApiKey(apiKeyModel);
}
return apiKeyModel;
}
/**
* 校验 ApiKey,成功返回 ApiKeyModel,失败则抛出异常
* @param apiKey /
* @return /
*/
public ApiKeyModel checkApiKey(String apiKey) {
ApiKeyModel ak = getApiKey(apiKey);
if(ak == null) {
throw new ApiKeyException("无效 API Key: " + apiKey).setApiKey(apiKey).setCode(SaApiKeyErrorCode.CODE_12301);
}
if(ak.timeExpired()) {
throw new ApiKeyException("API Key 已过期: " + apiKey).setApiKey(apiKey).setCode(SaApiKeyErrorCode.CODE_12302);
}
if(! ak.getIsValid()) {
throw new ApiKeyException("API Key 已被禁用: " + apiKey).setApiKey(apiKey).setCode(SaApiKeyErrorCode.CODE_12303);
}
return ak;
}
/**
* 持久化:ApiKeyModel
* @param ak /
*/
public void saveApiKey(ApiKeyModel ak) {
if(ak == null) {
return;
}
// 数据自检
ak.checkByCanSaved();
View on GitHub (pinned to ac2c7f6e94)
Solutions
- Issue a new key via createApiKey(...) and update the client with the new value
- For long-lived integrations, create the key with SaTokenDao.NEVER_EXPIRE or a multi-year window
- If expiry is intentional, rotate keys on a schedule before they lapse (monitor expiresIn())
Example fix
// before // key created with 1-hour expiry yesterday saApiKeyTemplate.checkApiKey(oldKey); // throws 12302 // after String newKey = saApiKeyTemplate.createApiKey(10001, "order-service", SaTokenDao.NEVER_EXPIRE); saApiKeyTemplate.checkApiKey(newKey);
Defensive patterns
Strategy: retry
Validate before calling
ApiKeyModel ak = saApiKeyTemplate.getApiKey(apiKey);
if (ak != null && ak.timeExpired()) {
apiKey = reissueKey(ak.getLoginId()); // createApiKey(...)
} Try / catch
catch (ApiKeyException e) { if (e.getCode() == SaApiKeyErrorCode.CODE_12302) { apiKey = reissue(); return retry(request); } throw e; } Prevention
- Monitor ak.expiresIn() and rotate before expiry
- For service-to-service keys choose NEVER_EXPIRE plus a revocation strategy, or long windows with scheduled rotation
When it happens
Trigger: Calling checkApiKey / checkApiKeyScope / checkApiKeyScopeOr with a key whose expiresTime timestamp is in the past (only keys created with a finite expiry can trigger this).
Common situations: Short-lived keys expiring between requests; long-running batch jobs using a key created at startup; clock skew between app servers; admin set a short expiry without noticing; key created with expiresTime accidentally in the past.
Related errors
AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14).
Data as JSON: /api/errors/b77434fe8f5f230d.
Report an issue: GitHub.