{"record":{"id":"c005d1790f88dd0a","repo":"usebruno/bruno","slug":"unsupported-grant-type-granttype-supported-ty","errorCode":null,"errorMessage":"Unsupported grant type: ${grantType}. Supported types: client_credentials, password","messagePattern":"Unsupported grant type: (.+?)\\. Supported types: client_credentials, password","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/bruno-requests/src/auth/oauth2-helper.ts","lineNumber":341,"sourceCode":"    credentialsId = 'default',\n    autoFetchToken = true,\n    tokenSource = 'access_token'\n  } = oauth2Config;\n\n  if (verbose) {\n    debug.enable('oauth2');\n  }\n\n  if (!grantType) {\n    throw new Error('Grant type is required for OAuth2');\n  }\n\n  if (!accessTokenUrl) {\n    throw new Error('Access token URL is required for OAuth2');\n  }\n\n  if (!['client_credentials', 'password'].includes(grantType)) {\n    throw new Error(`Unsupported grant type: ${grantType}. Supported types: client_credentials, password`);\n  }\n\n  // Check if we already have credentials stored\n  const existingToken = await tokenStore.getCredential({ url: accessTokenUrl, credentialsId });\n\n  if (existingToken) {\n    // Check if token is expired\n    if (!isTokenExpired(existingToken)) {\n      // Token is valid, use it\n      return tokenSource === 'id_token' ? existingToken.id_token : existingToken.access_token;\n    } else {\n      // Token is expired\n      if (autoFetchToken) {\n        // Clear expired token and proceed to fetch new token\n        await tokenStore.deleteCredential({ url: accessTokenUrl, credentialsId });\n      } else {\n        // Return expired token if autoFetchToken is disabled\n        return tokenSource === 'id_token' ? existingToken.id_token : existingToken.access_token;","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/usebruno/bruno/blob/9bdd81c7bdc57006e5f5ebffb79321a8d979f712/packages/bruno-requests/src/auth/oauth2-helper.ts#L323-L359","documentation":"Thrown by getOAuth2AccessToken when grantType is present and non-empty but is not one of the two supported values ('client_credentials' or 'password'). The check uses Array.includes, so even a typo or extra whitespace will fail it.","triggerScenarios":"grantType set to 'authorization_code', 'refresh_token', 'implicit', a misspelling like 'client-credentials', or a value with leading/trailing whitespace.","commonSituations":"User selected an unsupported grant type in a generic OAuth2 form; migrating from another library that supported more grant types; whitespace introduced by copy-paste from a doc.","solutions":["Use exactly 'client_credentials' or 'password' (underscores, no whitespace).","If you need authorization_code or refresh_token flows, this helper does not support them — use a different OAuth2 library (e.g. openid-client).","Trim and normalize the grantType string before passing it in."],"exampleFix":"// before\nconst config = { grantType: 'authorization_code', accessTokenUrl: url, clientId: id };\n\n// after\n// Use a library that supports auth-code flow, OR:\nconst config = { grantType: 'client_credentials', accessTokenUrl: url, clientId: id, clientSecret: secret };","handlingStrategy":"type-guard","validationCode":"const SUPPORTED = ['client_credentials', 'password'];\nif (!SUPPORTED.includes(config.grantType)) throw new Error(`Unsupported grantType: ${config.grantType}`);","typeGuard":"function isSupportedGrantType(c) {\n  return c.grantType === 'client_credentials' || c.grantType === 'password';\n}","tryCatchPattern":"try { await getOAuth2AccessToken(config, tokenStore); }\ncatch (e) { if (e.message.startsWith('Unsupported grant type')) { /* pick a supported flow */ } else throw e; }","preventionTips":["Trim and lowercase grantType before validation.","Maintain a const tuple of supported grants and derive the type from it.","If you need other flows, switch libraries — this helper will not grow new grant types."],"tags":["oauth2","validation","configuration","grant-type"],"backgroundTag":null,"analyzedSha":"9bdd81c7bdc57006e5f5ebffb79321a8d979f712","analyzedAt":"2026-08-13T04:09:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}