usebruno/bruno · error · Error

Access Token URL is required for OAuth2 client credentials f

Error message

Access Token URL is required for OAuth2 client credentials flow

What it means

Thrown by fetchTokenClientCredentials when the OAuth2Config.accessTokenUrl field is empty/undefined. The client-credentials grant needs a token endpoint to POST credentials to, so the helper refuses to build a request without one. It is a pre-flight validation guard, not a network error.

Source

Thrown at packages/bruno-requests/src/auth/oauth2-helper.ts:122

    return data;
  }
};

/**
 * Fetches an OAuth2 token using client credentials grant
 */
const fetchTokenClientCredentials = async (oauth2Config: OAuth2Config, axiosInstance?: AxiosInstance) => {
  const {
    accessTokenUrl,
    clientId,
    clientSecret,
    scope,
    credentialsPlacement = 'basic_auth_header',
    additionalParameters
  } = oauth2Config;

  if (!accessTokenUrl) {
    throw new Error('Access Token URL is required for OAuth2 client credentials flow');
  }

  if (!clientId) {
    throw new Error('Client ID is required for OAuth2 client credentials flow');
  }

  const requestConfig: RequestConfig = {
    method: 'POST',
    url: accessTokenUrl,
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Accept': 'application/json'
    },
    data: '',
    responseType: 'arraybuffer'
  };

  const data: ClientCredentialsData = {

View on GitHub (pinned to 9bdd81c7bd)

Solutions

  1. Set oauth2Config.accessTokenUrl to the full token endpoint URL (e.g. https://auth.example.com/oauth/token) before invoking the flow.
  2. If the URL comes from an env var, verify the variable is defined and non-empty at call time (console.log it in dev).
  3. Add a pre-call validation check (see validationCode) so the error surfaces in your code, not inside the helper.

Example fix

// before
const config = { grantType: 'client_credentials', clientId: 'abc', clientSecret: 'xyz' };
await getOAuth2AccessToken(config, tokenStore);

// after
const config = {
  grantType: 'client_credentials',
  accessTokenUrl: process.env.OAUTH_TOKEN_URL,
  clientId: 'abc',
  clientSecret: 'xyz'
};
await getOAuth2AccessToken(config, tokenStore);
Defensive patterns

Strategy: validation

Validate before calling

function validateClientCredentialsConfig(c) {
  if (!c.accessTokenUrl) throw new Error('accessTokenUrl missing for client_credentials flow');
  if (!c.clientId) throw new Error('clientId missing for client_credentials flow');
}
validateClientCredentialsConfig(config);

Type guard

function isClientCredentialsReady(c) {
  return c.grantType === 'client_credentials'
    && typeof c.accessTokenUrl === 'string' && c.accessTokenUrl.length > 0
    && typeof c.clientId === 'string' && c.clientId.length > 0;
}

Try / catch

try { await getOAuth2AccessToken(config, tokenStore); }
catch (e) { if (e.message.includes('Access Token URL is required')) { /* fill config */ } else throw e; }

Prevention

When it happens

Trigger: Calling getOAuth2AccessToken (or the Bruno auth pipeline) with grantType='client_credentials' but accessTokenUrl set to '', null, undefined, or omitted. This includes configs loaded from a collection where the token URL field was left blank by the user.

Common situations: User created an OAuth2 collection item but never filled the 'Access Token URL' field; env variable referencing the URL resolved to empty; config object assembled programmatically and the accessTokenUrl key was misspelled or destructured away.

Related errors


AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13). Data as JSON: /api/errors/f86455f18f370a8f. Report an issue: GitHub.