usebruno/bruno · error · Error
Client ID is required for OAuth2 client credentials flow
Error message
Client ID is required for OAuth2 client credentials flow
What it means
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.
Source
Thrown at packages/bruno-requests/src/auth/oauth2-helper.ts:126
/**
* 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 = {
grant_type: 'client_credentials'
};
if (scope && scope.trim() !== '') {View on GitHub (pinned to 9bdd81c7bd)
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.
Example fix
// before
const config = { grantType: 'client_credentials', accessTokenUrl: tokenUrl, clientSecret: secret };
// after
const config = {
grantType: 'client_credentials',
accessTokenUrl: tokenUrl,
clientId: process.env.OAUTH_CLIENT_ID,
clientSecret: secret
}; Defensive patterns
Strategy: validation
Validate before calling
if (!config.clientId) throw new Error('OAUTH_CLIENT_ID env var is not set');
await getOAuth2AccessToken(config, tokenStore); Type guard
function hasClientId(c) { return typeof c.clientId === 'string' && c.clientId.trim().length > 0; } Try / catch
try { await getOAuth2AccessToken(config, tokenStore); }
catch (e) { if (e.message === 'Client ID is required for OAuth2 client credentials flow') { /* load secret */ } else throw e; } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Access Token URL is required for OAuth2 client credentials f
- Password is required for OAuth2 password credentials flow
- Client ID is required for OAuth2 password credentials flow
- Access Token URL is required for OAuth2 password credentials
- Username is required for OAuth2 password credentials flow
AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13).
Data as JSON: /api/errors/91de575850beb3f7.
Report an issue: GitHub.