{"record":{"id":"c682d3742c67370a","repo":"dromara/Sa-Token","slug":"30126","errorCode":"30126","errorMessage":"无效 grant_type：","messagePattern":"无效 grant_type：","errorType":"exception","errorClass":"SaOAuth2Exception","httpStatus":null,"severity":"error","filePath":"sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/processor/SaOAuth2ServerProcessor.java","lineNumber":301,"sourceCode":"\t\t}\n\n\t\t// 默认返回\n\t\tthrow new SaOAuth2Exception(\"无效response_type: \" + ra.responseType).setCode(SaOAuth2ErrorCode.CODE_30125);\n\t}\n\n\t/**\n\t * 模式四：凭证式\n\t * @return 处理结果\n\t */\n\tpublic Object clientToken() {\n\t\t// 获取变量\n\t\tSaRequest req = SaHolder.getRequest();\n\t\tSaOAuth2ServerConfig cfg = SaOAuth2Manager.getServerConfig();\n\t\tSaOAuth2Template oauth2Template = SaOAuth2Manager.getTemplate();\n\n\t\tString grantType = req.getParamNotNull(Param.grant_type);\n\t\tif(!grantType.equals(GrantType.client_credentials)) {\n\t\t\tthrow new SaOAuth2Exception(\"无效 grant_type：\" + grantType).setCode(SaOAuth2ErrorCode.CODE_30126);\n\t\t}\n\t\tif(!cfg.enableClientCredentials) {\n\t\t\tthrowErrorSystemNotEnableModel();\n\t\t}\n\t\tif(!currClientModel().getAllowGrantTypes().contains(GrantType.client_credentials)) {\n\t\t\tthrowErrorClientNotEnableModel();\n\t\t}\n\n\t\t// 获取参数\n\t\tClientIdAndSecretModel clientIdAndSecret = SaOAuth2Manager.getDataResolver().readClientIdAndSecret(req);\n\t\tString clientId = clientIdAndSecret.clientId;\n\t\tString clientSecret = clientIdAndSecret.clientSecret;\n\t\tList<String> scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(req.getParam(Param.scope));\n\n\t\t// 校验 ClientScope\n\t\toauth2Template.checkContractScope(clientId, scopes);\n\n\t\t// 校验 ClientSecret","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/dromara/Sa-Token/blob/ac2c7f6e94a78573cf0bcb932dd8b04e68fad189/sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/processor/SaOAuth2ServerProcessor.java#L283-L319","documentation":"Thrown by SaOAuth2ServerProcessor.clientToken: the client-credentials endpoint (/oauth2/client_token) requires grant_type=client_credentials exactly. Any other value (including authorization_code or password, which belong on /oauth2/token) is rejected before config and client checks run. Error code 30126.","triggerScenarios":"POST /oauth2/client_token with grant_type=password or grant_type=authorization_code; grant_type missing or misspelled (e.g. 'clientcredential').","commonSituations":"Developer points all token requests at the wrong endpoint; copy-pasted token request from password flow reused against client_token; trailing whitespace in the parameter.","solutions":["Use grant_type=client_credentials on /oauth2/client_token","For authorization_code or password grants, call /oauth2/token instead","Trim and verify the exact spelling of grant_type before sending"],"exampleFix":"# before\ncurl -X POST http://host/oauth2/client_token -d 'grant_type=password&username=x&password=y'\n\n# after\ncurl -X POST http://host/oauth2/client_token \\\n  -u 1001:secret -d 'grant_type=client_credentials&scope=all'","handlingStrategy":"validation","validationCode":"if(!\"client_credentials\".equals(grantType)) {\n    throw new IllegalArgumentException(\"/oauth2/client_token only accepts grant_type=client_credentials\");\n}","typeGuard":null,"tryCatchPattern":"catch(SaOAuth2Exception e) { if(\"30126\".equals(e.getCode())) return badRequest(\"invalid grant_type for this endpoint\"); }","preventionTips":["Use one token-client class per grant type so endpoints cannot be mixed up","Document endpoint-to-grant-type mapping next to client credential config"],"tags":["oauth2","grant-type","client-credentials","sa-token"],"backgroundTag":null,"analyzedSha":"ac2c7f6e94a78573cf0bcb932dd8b04e68fad189","analyzedAt":"2026-08-14T14:36:10.271Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}