dromara/Sa-Token · error · ApiKeyException
12304
12304
Error message
ApiKey 值不可为空
What it means
ApiKeyException with error code 12304 thrown by ApiKeyModel.checkByCanSaved() — the pre-persistence sanity check — when the apiKey field is empty (SaFoxUtil.isEmpty). checkByCanSaved is run before saving an ApiKeyModel to storage; the same method also enforces loginId, createTime, expiresTime and isValid, each failing with code 12304 but distinct messages.
Source
Thrown at sa-token-plugin/sa-token-apikey/src/main/java/cn/dev33/satoken/apikey/model/ApiKeyModel.java:143
return this.extraData.get(key);
}
/**
* 删除扩展数据
*/
public Object removeExtra(String key) {
if (this.extraData == null) {
return null;
}
return this.extraData.remove(key);
}
/**
* 数据自检,判断是否可以保存入库
*/
public void checkByCanSaved() {
if (SaFoxUtil.isEmpty(this.apiKey)) {
throw new ApiKeyException("ApiKey 值不可为空").setApiKey(apiKey).setCode(SaApiKeyErrorCode.CODE_12304);
}
if (this.loginId == null) {
throw new ApiKeyException("无效 ApiKey: " + apiKey).setApiKey(apiKey).setCode(SaApiKeyErrorCode.CODE_12304);
}
if (this.createTime == 0) {
throw new ApiKeyException("请指定 createTime 创建时间").setApiKey(apiKey).setCode(SaApiKeyErrorCode.CODE_12304);
}
if (this.expiresTime == 0) {
throw new ApiKeyException("请指定 expiresTime 过期时间").setApiKey(apiKey).setCode(SaApiKeyErrorCode.CODE_12304);
}
if (this.isValid == null) {
throw new ApiKeyException("请指定 isValid 是否生效").setApiKey(apiKey).setCode(SaApiKeyErrorCode.CODE_12304);
}
}
/**
* 获取:此 ApiKey 的剩余有效期(秒), -1=永不过期
* @return /View on GitHub (pinned to ac2c7f6e94)
Solutions
- Generate a key before saving: use the plugin's key generator (e.g. SaFoxUtil / apiKeyManager random generator) or supply a non-empty unique value.
- If the key comes from user input, validate it is non-blank at the API boundary and return a 400 instead of letting persistence fail.
- For the sibling messages, also set loginId, createTime, expiresTime (non-zero) and isValid before save.
- Catch ApiKeyException and read getCode()==12304 to map to a client-facing validation error.
Example fix
// before ApiKeyModel model = new ApiKeyModel(); model.setLoginId(10001); model.setCreateTime(System.currentTimeMillis()); model.setExpiresTime(System.currentTimeMillis() + 86400000L); model.setIsValid(true); saApiKeyTemplate.save(model); // throws 12304: apiKey empty // after model.setApiKey(SaFoxUtil.getRandomString(32)); // or framework-generated key saApiKeyTemplate.save(model);
Defensive patterns
Strategy: validation
Validate before calling
ApiKeyModel m = new ApiKeyModel(); m.setApiKey(generateKey()); // non-empty m.setLoginId(loginId); // non-null m.setCreateTime(System.currentTimeMillis()); m.setExpiresTime(System.currentTimeMillis() + ttlMs); m.setIsValid(true); m.checkByCanSaved(); // passes silently now
Type guard
boolean isSavable(ApiKeyModel m) { return SaFoxUtil.isNotEmpty(m.getApiKey()) && m.getLoginId() != null && m.getCreateTime() > 0 && m.getExpiresTime() > 0 && m.getIsValid() != null; } Try / catch
try { manager.save(model); } catch (ApiKeyException e) { if (e.getCode() == SaApiKeyErrorCode.CODE_12304) { // map to 400 validation error using e.getMessage() } else throw e; } Prevention
- Call checkByCanSaved() yourself in a validate step before persisting so failures surface at the API boundary.
- Never hand-roll the apiKey value from user input; generate it server-side (random, unique) and return it once.
When it happens
Trigger: Building an ApiKeyModel manually and calling save/create without setting apiKey — e.g. constructing new ApiKeyModel(), setting loginId and times, then calling the manager's create/save which invokes checkByCanSaved(). Only this first check yields the 'ApiKey 值不可为空' message; a null apiKey from a client-supplied payload hits it directly.
Common situations: Integrating the sa-token-apikey plugin and hand-assembling the model instead of letting the framework generate the key; trimming/normalizing a client-provided key to empty string before save; API payloads where apiKey is optional on input but required at persistence.
Related errors
AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14).
Data as JSON: /api/errors/088f5d451024a3fe.
Report an issue: GitHub.