dromara/Sa-Token · error · ApiKeyScopeException
12311
12311
Error message
该 API Key 不具备 Scope:
What it means
Thrown by SaApiKeyTemplate.checkApiKeyScope(String, String...) in AND mode: the key passes checkApiKey but its scopes list does not contain one of the required scopes. Code 12311 is the ApiKeyScopeException error code; the exception carries the missing scope.
Source
Thrown at sa-token-plugin/sa-token-apikey/src/main/java/cn/dev33/satoken/apikey/template/SaApiKeyTemplate.java:315
return true;
} catch (ApiKeyException e) {
return false;
}
}
/**
* 校验:指定 ApiKey 是否具有指定 Scope 列表 (AND 模式,需要全部具备),如果不具备则抛出异常
* @param apiKey ApiKey
* @param scopes 需要校验的权限列表
*/
public void checkApiKeyScope(String apiKey, String... scopes) {
ApiKeyModel ak = checkApiKey(apiKey);
if(SaFoxUtil.isEmptyArray(scopes)) {
return;
}
for (String scope : scopes) {
if(! ak.getScopes().contains(scope)) {
throw new ApiKeyScopeException("该 API Key 不具备 Scope:" + scope)
.setApiKey(apiKey)
.setScope(scope)
.setCode(SaApiKeyErrorCode.CODE_12311);
}
}
}
/**
* 判断:指定 ApiKey 是否具有指定 Scope 列表 (OR 模式,具备其一即可),返回 true 或 false
* @param apiKey ApiKey
* @param scopes 需要校验的权限列表
*/
public boolean hasApiKeyScopeOr(String apiKey, String... scopes) {
try {
checkApiKeyScopeOr(apiKey, scopes);
return true;
} catch (ApiKeyException e) {
return false;View on GitHub (pinned to ac2c7f6e94)
Solutions
- Re-create the key including the missing scope: createApiKey(loginId, clientToken, timeout, scopes) with the full required set
- Check for typos/case mismatch between the scope string required by the code and the one stored on the key
- Inspect the stored scopes first: saApiKeyTemplate.getApiKey(apiKey).getScopes()
Example fix
// before
// key created with scopes "userinfo" only
saApiKeyTemplate.checkApiKeyScope(apiKey, "userinfo", "order"); // throws 12311
// after
String key = saApiKeyTemplate.createApiKey(10001, "svc", 3600*24, Arrays.asList("userinfo", "order"));
saApiKeyTemplate.checkApiKeyScope(key, "userinfo", "order"); Defensive patterns
Strategy: validation
Validate before calling
ApiKeyModel ak = saApiKeyTemplate.getApiKey(apiKey);
Set<String> need = new HashSet<>(Arrays.asList("userinfo", "order"));
if (ak == null || !ak.getScopes().containsAll(need)) {
return forbidden("missing scope");
} Try / catch
catch (ApiKeyScopeException e) { if (e.getCode() == SaApiKeyErrorCode.CODE_12311) { /* 403 with required scopes listed */ } } Prevention
- Issue keys with the exact scope set each endpoint requires; document scopes per route
- Store scope strings in shared constants to avoid typos between issuance and enforcement
When it happens
Trigger: Calling checkApiKeyScope(apiKey, "userinfo", "order") when the key's scopes collection lacks at least one of them (all must be present); annotation-based scope checks on a route hit the same path.
Common situations: Key was issued with scopes ["userinfo"] but the endpoint now requires ["userinfo","pay"]; scope naming mismatch ("user-info" vs "userinfo", case); adding a new required scope to an API without re-issuing keys.
Related errors
AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14).
Data as JSON: /api/errors/637beab6eca3c6cc.
Report an issue: GitHub.