{"record":{"id":"91de575850beb3f7","repo":"usebruno/bruno","slug":"client-id-is-required-for-oauth2-client-credential","errorCode":null,"errorMessage":"Client ID is required for OAuth2 client credentials flow","messagePattern":"Client ID is required for OAuth2 client credentials flow","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/bruno-requests/src/auth/oauth2-helper.ts","lineNumber":126,"sourceCode":"/**\n * Fetches an OAuth2 token using client credentials grant\n */\nconst fetchTokenClientCredentials = async (oauth2Config: OAuth2Config, axiosInstance?: AxiosInstance) => {\n  const {\n    accessTokenUrl,\n    clientId,\n    clientSecret,\n    scope,\n    credentialsPlacement = 'basic_auth_header',\n    additionalParameters\n  } = oauth2Config;\n\n  if (!accessTokenUrl) {\n    throw new Error('Access Token URL is required for OAuth2 client credentials flow');\n  }\n\n  if (!clientId) {\n    throw new Error('Client ID is required for OAuth2 client credentials flow');\n  }\n\n  const requestConfig: RequestConfig = {\n    method: 'POST',\n    url: accessTokenUrl,\n    headers: {\n      'Content-Type': 'application/x-www-form-urlencoded',\n      'Accept': 'application/json'\n    },\n    data: '',\n    responseType: 'arraybuffer'\n  };\n\n  const data: ClientCredentialsData = {\n    grant_type: 'client_credentials'\n  };\n\n  if (scope && scope.trim() !== '') {","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/usebruno/bruno/blob/9bdd81c7bdc57006e5f5ebffb79321a8d979f712/packages/bruno-requests/src/auth/oauth2-helper.ts#L108-L144","documentation":"Thrown by fetchTokenClientCredentials when oauth2Config.clientId is falsy. The client_credentials grant authenticates the application itself (not a user), so a client_id is mandatory to identify the app to the authorization server. Without it the token request is malformed.","triggerScenarios":"getOAuth2AccessToken called with grantType='client_credentials' and a valid accessTokenUrl, but clientId omitted, empty, or undefined. Common when secrets are sourced from env vars that are not set in the current environment.","commonSituations":"CI/CD pipeline forgot to inject OAUTH_CLIENT_ID; the clientId was stored only in the Bruno GUI collection but not serialized into the programmatic config; a refactor renamed the field.","solutions":["Provide a non-empty clientId in the OAuth2Config for client_credentials requests.","Confirm the env var / secret store actually returns the client id (check for trailing whitespace or undefined).","Gate the call with a guard that fails fast with a clearer message than the helper's."],"exampleFix":"// before\nconst config = { grantType: 'client_credentials', accessTokenUrl: tokenUrl, clientSecret: secret };\n\n// after\nconst config = {\n  grantType: 'client_credentials',\n  accessTokenUrl: tokenUrl,\n  clientId: process.env.OAUTH_CLIENT_ID,\n  clientSecret: secret\n};","handlingStrategy":"validation","validationCode":"if (!config.clientId) throw new Error('OAUTH_CLIENT_ID env var is not set');\nawait getOAuth2AccessToken(config, tokenStore);","typeGuard":"function hasClientId(c) { return typeof c.clientId === 'string' && c.clientId.trim().length > 0; }","tryCatchPattern":"try { await getOAuth2AccessToken(config, tokenStore); }\ncatch (e) { if (e.message === 'Client ID is required for OAuth2 client credentials flow') { /* load secret */ } else throw e; }","preventionTips":["Load all OAuth2 credentials from a single secrets module that fails fast on missing values.","Assert env vars are present at process startup, not at first token fetch.","Trim whitespace from config values sourced from user input."],"tags":["oauth2","validation","configuration","client-credentials","secrets"],"backgroundTag":null,"analyzedSha":"9bdd81c7bdc57006e5f5ebffb79321a8d979f712","analyzedAt":"2026-08-13T04:09:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}