usebruno/bruno · error · Error
${JSON.stringify(tokenResponse)}
Error message
${JSON.stringify(tokenResponse)} What it means
Thrown when the token endpoint returned an HTTP response containing an 'error' field — i.e. the authorization server rejected the token request (invalid_client, invalid_grant, invalid_scope, etc.). The helper serializes the entire response body as JSON so the caller sees the server's error object verbatim.
Source
Thrown at packages/bruno-requests/src/auth/oauth2-helper.ts:382
if (!autoFetchToken) {
// Don't fetch token if autoFetchToken is disabled
return null;
}
// Otherwise, proceed to fetch new token
}
let tokenResponse;
if (grantType === 'client_credentials') {
tokenResponse = await fetchTokenClientCredentials(oauth2Config, axiosInstance);
} else if (grantType === 'password') {
tokenResponse = await fetchTokenPassword(oauth2Config, axiosInstance);
} else {
throw new Error(`Unsupported grant type: ${grantType}`);
}
if (tokenResponse.error) {
throw new Error(JSON.stringify(tokenResponse));
}
if (!tokenResponse || !tokenResponse.access_token) {
throw new Error('No access token received from server');
}
if (tokenResponse.expires_in && tokenResponse.created_at) {
tokenResponse.expires_at = tokenResponse.created_at + tokenResponse.expires_in * 1000;
}
const saved = await tokenStore.saveCredential({ url: accessTokenUrl, credentialsId, credentials: tokenResponse });
if (!saved) {
console.warn('OAuth2: Failed to save token to store, but proceeding with token');
}
return tokenSource === 'id_token' ? tokenResponse.id_token : tokenResponse.access_token;
};
View on GitHub (pinned to 9bdd81c7bd)
Solutions
- Parse the thrown message as JSON to read error and error_description — the exact server reason is there.
- For 'invalid_client': recheck clientId/clientSecret and credentialsPlacement (basic_auth_header vs body).
- For 'invalid_grant' with password flow: confirm username/password are correct and the account is active.
- For 'invalid_scope': trim the requested scopes to those registered for the client.
Example fix
// before — opaque error bubbling up
try { await getOAuth2AccessToken(config, tokenStore); }
catch (e) { console.log(e.message); }
// after — decode the server's error object
try { await getOAuth2AccessToken(config, tokenStore); }
catch (e) {
try {
const body = JSON.parse(e.message);
console.error('OAuth2 error:', body.error, '-', body.error_description);
} catch {
console.error('Unexpected error:', e.message);
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// Cannot fully prevent — server-side rejection. Validate inputs to reduce likelihood:
if (config.credentialsPlacement && !['basic_auth_header','body'].includes(config.credentialsPlacement)) {
throw new Error('Bad credentialsPlacement');
} Try / catch
try { await getOAuth2AccessToken(config, tokenStore); }
catch (e) {
let body;
try { body = JSON.parse(e.message); } catch { /* not a token-response error */ throw e; }
if (body && body.error) {
console.error('Token endpoint rejected:', body.error, body.error_description);
// branch on body.error: invalid_client -> fix secret, invalid_grant -> re-auth, etc.
} else throw e;
} Prevention
- Log the parsed error body to classify token-endpoint failures.
- Double-check credentialsPlacement matches what the server expects (header vs body).
- Rotate client secrets on a schedule so expired secrets surface in tooling, not at runtime.
When it happens
Trigger: Token request reached the server but the server responded with an OAuth2 error body, e.g. {error:'invalid_client', error_description:'...'} because of wrong client secret, bad credentials, or an unauthorized scope.
Common situations: Wrong client secret; expired/revoked refresh material; requested scope not permitted for the client; clock skew causing assertion failures; user account locked when using password grant.
Related errors
- No access token received from server
- ${response.error}
- Failed to minify
- credentialId must be a non-empty string
- getRandomValues: Constructor ${obj.type} is not available
AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13).
Data as JSON: /api/errors/ed625111a7714922.
Report an issue: GitHub.