dromara/Sa-Token · error · SaOAuth2Exception
30126
30126
Error message
无效 grant_type:
What it means
Thrown by SaOAuth2Strategy.grantTypeAuth: the grant_type parameter does not match any registered grant-type handler. Built-in handlers cover authorization_code and password (plus client_credentials on its own endpoint); anything unknown fails this lookup. Error code 30126.
Source
Thrown at sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/strategy/SaOAuth2Strategy.java:191
SaManager.getLog().info("自定义 GRANT_TYPE [{}] (处理器: {})", handler.getHandlerGrantType(), handler.getClass().getCanonicalName());
}
/**
* 移除一个 grant_type 处理器
*/
public void removeGrantTypeHandler(String scope) {
grantTypeHandlerMap.remove(scope);
}
/**
* 根据 grantType 构造一个 AccessTokenModel
*/
public SaOAuth2GrantTypeAuthFunction grantTypeAuth = (req) -> {
// 先校验提供的 grant_type 是否有效
String grantType = req.getParamNotNull(SaOAuth2Consts.Param.grant_type);
SaOAuth2GrantTypeHandlerInterface grantTypeHandler = grantTypeHandlerMap.get(grantType);
if(grantTypeHandler == null) {
throw new SaOAuth2Exception("无效 grant_type: " + grantType).setCode(SaOAuth2ErrorCode.CODE_30126);
}
// 针对 authorization_code 与 password 两种特殊 grant_type,需要判断全局是否开启
SaOAuth2ServerConfig config = SaOAuth2Manager.getServerConfig();
if(grantType.equals(GrantType.authorization_code) && !config.getEnableAuthorizationCode() ) {
throw new SaOAuth2Exception("系统未开放的 grant_type: " + grantType).setCode(SaOAuth2ErrorCode.CODE_30126);
}
if(grantType.equals(GrantType.password) && !config.getEnablePassword() ) {
throw new SaOAuth2Exception("系统未开放的 grant_type: " + grantType).setCode(SaOAuth2ErrorCode.CODE_30126);
}
// 校验 clientSecret 和 scope
ClientIdAndSecretModel clientIdAndSecretModel = SaOAuth2Manager.getDataResolver().readClientIdAndSecret(req);
List<String> scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(req.getParam(SaOAuth2Consts.Param.scope));
SaClientModel clientModel = SaOAuth2Manager.getTemplate().checkClientSecretAndScope(clientIdAndSecretModel.getClientId(), clientIdAndSecretModel.getClientSecret(), scopes);
// 检测应用是否开启此 grantType
if(!clientModel.getAllowGrantTypes().contains(grantType)) {View on GitHub (pinned to ac2c7f6e94)
Solutions
- Use a supported grant_type: authorization_code or password on /oauth2/token (client_credentials goes to /oauth2/client_token)
- For custom grant types, register the handler before use: SaOAuth2Strategy.instance.addGrantTypeHandler("my_grant", handler)
- Check for typos/whitespace in the grant_type parameter
Example fix
// before
// custom grant type used but never registered
POST /oauth2/token grant_type=my_grant
// after
SaOAuth2Strategy.instance.addGrantTypeHandler("my_grant", new MyGrantTypeHandler());
POST /oauth2/token grant_type=my_grant Defensive patterns
Strategy: validation
Validate before calling
Set<String> supported = new HashSet<>(Arrays.asList("authorization_code", "password"));
// plus any handler you registered via addGrantTypeHandler
if(!supported.contains(grantType)) {
throw new IllegalArgumentException("unsupported grant_type: " + grantType);
} Try / catch
catch(SaOAuth2Exception e) { if("30126".equals(e.getCode())) return badRequest("invalid grant_type: " + e.getMessage()); } Prevention
- Register custom grant-type handlers in application init, before any request can arrive
- Log registered handler keys at startup to catch missing registrations
When it happens
Trigger: POST /oauth2/token with grant_type values such as 'refresh_token' when no such handler is registered, 'client_credentials' (handled on /oauth2/client_token, not here), typos, or a custom grant type whose handler was never added via addGrantTypeHandler.
Common situations: Developer expects standard OAuth2 refresh_token support out of the box; custom grant type defined but handler registration missing or keyed under a different string; version upgrade where a custom handler was registered on a different strategy instance.
Related errors
AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14).
Data as JSON: /api/errors/aafa52f45426aa28.
Report an issue: GitHub.