usebruno/bruno · error · Error
Client ID is required for OAuth2 password credentials flow
Error message
Client ID is required for OAuth2 password credentials flow
What it means
Thrown by fetchTokenPassword when oauth2Config.clientId is falsy. Even the password grant requires a client_id so the authorization server can identify the requesting application; the helper validates it after username/password checks.
Source
Thrown at packages/bruno-requests/src/auth/oauth2-helper.ts:227
scope,
credentialsPlacement = 'basic_auth_header',
additionalParameters
} = oauth2Config;
if (!accessTokenUrl) {
throw new Error('Access Token URL is required for OAuth2 password credentials flow');
}
if (!username) {
throw new Error('Username is required for OAuth2 password credentials flow');
}
if (!password) {
throw new Error('Password is required for OAuth2 password credentials flow');
}
if (!clientId) {
throw new Error('Client ID is required for OAuth2 password 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: PasswordGrantData = {
grant_type: 'password',
username,
password
};View on GitHub (pinned to 9bdd81c7bd)
Solutions
- Provide a non-empty clientId for the application registered with the authorization server.
- Verify the client registration includes the password grant as an allowed flow.
- Load clientId from a single source of truth and assert it is set at startup.
Example fix
// before
const config = { grantType: 'password', accessTokenUrl: url, username: user, password: pass };
// after
const config = {
grantType: 'password',
accessTokenUrl: url,
username: user,
password: pass,
clientId: process.env.OAUTH_CLIENT_ID
}; Defensive patterns
Strategy: validation
Validate before calling
if (!config.clientId) throw new Error('clientId required even for password grant'); Type guard
function hasClientIdForPassword(c) { return typeof c.clientId === 'string' && c.clientId.length > 0; } Try / catch
try { await getOAuth2AccessToken(config, tokenStore); }
catch (e) { if (e.message.includes('Client ID is required for OAuth2 password')) { /* set clientId */ } else throw e; } Prevention
- Register the client for the password grant at the authorization server.
- Treat clientId as mandatory for every grant this helper supports.
- Centralize clientId in one config constant.
When it happens
Trigger: getOAuth2AccessToken with grantType='password', valid accessTokenUrl/username/password, but clientId empty/undefined.
Common situations: Public-client setup where the developer assumed client_id is optional; the clientId env var missing in production; config assembled from multiple sources and the clientId branch was skipped.
Related errors
- Password is required for OAuth2 password credentials flow
- Client ID is required for OAuth2 client credentials flow
- Access Token URL is required for OAuth2 password credentials
- Username is required for OAuth2 password credentials flow
- Access Token URL is required for OAuth2 client credentials f
AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13).
Data as JSON: /api/errors/147ce35b734a647c.
Report an issue: GitHub.