usebruno/bruno · error · Error
Access token URL is required for OAuth2
Error message
Access token URL is required for OAuth2
What it means
Thrown by getOAuth2AccessToken when grantType is present but accessTokenUrl is falsy. This is the top-level URL check, distinct from the per-flow checks at lines 122/215; it runs after the grant-type check and before the supported-grant-type check, so it catches the omission regardless of flow.
Source
Thrown at packages/bruno-requests/src/auth/oauth2-helper.ts:337
export const getOAuth2Token = async (oauth2Config: OAuth2Config, tokenStore: TokenStore, verbose: string, axiosInstance?: AxiosInstance): Promise<string | null> => {
const {
grantType,
accessTokenUrl,
credentialsId = 'default',
autoFetchToken = true,
tokenSource = 'access_token'
} = oauth2Config;
if (verbose) {
debug.enable('oauth2');
}
if (!grantType) {
throw new Error('Grant type is required for OAuth2');
}
if (!accessTokenUrl) {
throw new Error('Access token URL is required for OAuth2');
}
if (!['client_credentials', 'password'].includes(grantType)) {
throw new Error(`Unsupported grant type: ${grantType}. Supported types: client_credentials, password`);
}
// Check if we already have credentials stored
const existingToken = await tokenStore.getCredential({ url: accessTokenUrl, credentialsId });
if (existingToken) {
// Check if token is expired
if (!isTokenExpired(existingToken)) {
// Token is valid, use it
return tokenSource === 'id_token' ? existingToken.id_token : existingToken.access_token;
} else {
// Token is expired
if (autoFetchToken) {
// Clear expired token and proceed to fetch new tokenView on GitHub (pinned to 9bdd81c7bd)
Solutions
- Populate accessTokenUrl with the authorization server's token endpoint.
- If the URL is templated, resolve it (env substitution) before passing the config to the helper.
- Add an assertion at config build time so missing URLs fail loudly and early.
Example fix
// before
const config = { grantType: 'client_credentials', clientId: id, clientSecret: secret };
// after
const config = {
grantType: 'client_credentials',
accessTokenUrl: process.env.OAUTH_TOKEN_URL || 'https://auth.example.com/oauth/token',
clientId: id,
clientSecret: secret
}; Defensive patterns
Strategy: validation
Validate before calling
if (!config.accessTokenUrl) throw new Error('accessTokenUrl must be set on OAuth2Config'); Type guard
function hasAccessTokenUrl(c) { return typeof c.accessTokenUrl === 'string' && c.accessTokenUrl.length > 0; } Try / catch
try { await getOAuth2AccessToken(config, tokenStore); }
catch (e) { if (e.message === 'Access token URL is required for OAuth2') { /* set URL */ } else throw e; } Prevention
- Run env substitution on the URL before calling the helper.
- Validate that the URL parses with new URL(...) to catch malformed values.
- This top-level check pre-empts errors 380/382, so fixing it early removes a whole class of errors.
When it happens
Trigger: Calling getOAuth2AccessToken with a valid grantType but no accessTokenUrl. Note this fires before flow-specific helpers, so it pre-empts errors 380 and 382.
Common situations: Config built from a template that left the token URL as a placeholder; env var for the URL not set in the deployed environment; the URL was stripped by a sanitizer.
Related errors
- Access Token URL is required for OAuth2 client credentials f
- 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
- Password is required for OAuth2 password credentials flow
AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13).
Data as JSON: /api/errors/535ba76e5d8b3184.
Report an issue: GitHub.