langgenius/dify · error · BadRequest
invalid grant_type
Error message
invalid grant_type
What it means
Flask BadRequest (HTTP 400) raised at oauth_server.py:204 in OAuthServerUserTokenApi.post (POST /console/api/oauth/provider/token) when OAuthGrantType(payload.grant_type) raises ValueError — the supplied grant_type string is not one of the enum members (e.g. not 'authorization_code' or 'refresh_token'). This is the first validation in the token endpoint.
Source
Thrown at api/controllers/console/auth/oauth_server.py:204
return jsonable_encoder(
{
"code": code,
}
)
@console_ns.route("/oauth/provider/token")
class OAuthServerUserTokenApi(Resource):
@setup_required
@console_ns.expect(console_ns.models[OAuthTokenRequest.__name__])
@console_ns.response(200, "Success", console_ns.models[OAuthProviderTokenResponse.__name__])
@oauth_server_client_id_required
@model_validate(OAuthTokenRequest)
def post(self, payload: OAuthTokenRequest, oauth_provider_app: OAuthProviderApp):
try:
grant_type = OAuthGrantType(payload.grant_type)
except ValueError:
raise BadRequest("invalid grant_type")
match grant_type:
case OAuthGrantType.AUTHORIZATION_CODE:
if not payload.code:
raise BadRequest("code is required")
if payload.client_secret != oauth_provider_app.client_secret:
raise BadRequest("client_secret is invalid")
if payload.redirect_uri not in oauth_provider_app.redirect_uris:
raise BadRequest("redirect_uri is invalid")
access_token, refresh_token = OAuthServerService.sign_oauth_access_token(
grant_type, code=payload.code, client_id=oauth_provider_app.client_id
)
return jsonable_encoder(
{
"access_token": access_token,
"token_type": "Bearer",View on GitHub (pinned to ef8544b173)
Solutions
- Use only the grant_type values the server supports: 'authorization_code' to exchange a code, or 'refresh_token' to rotate tokens.
- Check the OAuthGrantType enum definition for the canonical string values and match them exactly (case-sensitive).
- Ensure the field is present in the JSON body — an empty/None value will also fail enum construction.
- Update the client if a version change altered the accepted grant_type strings.
Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED = new Set(['authorization_code', 'refresh_token']);
if (!ALLOWED.has(grantType)) {
throw new Error(`Unsupported grant_type '${grantType}'`);
} Type guard
function isSupportedGrantType(v: string): v is 'authorization_code' | 'refresh_token' {
return v === 'authorization_code' || v === 'refresh_token';
} Try / catch
try {
await requestToken({grant_type: grantType, ...});
} catch (e) {
if (/invalid grant_type/i.test(e.message)) { correctGrantType(); } else throw e;
} Prevention
- Match grant_type strings exactly (case-sensitive) to the enum.
- Do not attempt unsupported flows (password, client_credentials).
- Re-read the enum after library upgrades.
When it happens
Trigger: POST /oauth/provider/token with a grant_type the server does not recognize (typo, unsupported value like 'password' or 'client_credentials', or missing). The enum constructor raises ValueError -> caught -> BadRequest.
Common situations: OAuth client built for a different grant flow than this server supports; schema drift after an upgrade that renamed grant types; or a malformed test payload.
Related errors
- code is required
- refresh_token is required
- invalid_email
- redirect_uri is invalid
- client_secret is invalid
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/3b4864833ec0f0dc.
Report an issue: GitHub.