usebruno/bruno · error · Error

No access token received from server

Error message

No access token received from server

What it means

Thrown when the token endpoint returned a 2xx response that parsed cleanly and contained no 'error' field, but the body had no access_token. The helper cannot proceed because there is no credential to return or store.

Source

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

    // 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

  1. Inspect the raw token response (add logging before the helper or capture network traffic) to see what body the server actually returns.
  2. If the server uses a non-standard key, normalize the response before relying on this helper, or open a provider-compatibility issue.
  3. Confirm you are not hitting an HTML login page (200 + HTML) because the token URL points at the wrong endpoint.
  4. If only an id_token is issued, set tokenSource:'id_token' — but note this error still fires because the access_token check happens first.

Example fix

// before
const config = { grantType: 'client_credentials', accessTokenUrl: url, clientId: id, clientSecret: secret };
// tokenResponse from server = { accessToken: '...' }  // non-standard key

// after — point at the correct token endpoint that returns RFC6749 { access_token, token_type, expires_in }
Defensive patterns

Strategy: try-catch

Validate before calling

// Cannot prevent from client side; pre-validate the URL points at the real token endpoint:
try { new URL(config.accessTokenUrl); } catch { throw new Error('accessTokenUrl is not a valid URL'); }

Try / catch

try { await getOAuth2AccessToken(config, tokenStore); }
catch (e) {
  if (e.message === 'No access token received from server') {
    // capture the raw response separately to inspect its shape
    console.error('Token endpoint did not return access_token; verify RFC6749 compliance');
  } else throw e;
}

Prevention

When it happens

Trigger: Token server returned 200 with an unexpected body shape (e.g. returned only an id_token, or returned the token under a non-standard key like 'accessToken'), or returned an empty object.

Common situations: Server misconfiguration returning the token under a camelCase key instead of access_token; partial response truncated by a proxy; the server issued only an id_token but tokenSource was left at its default 'access_token'; OAuth2 provider returning a non-RFC6749 compliant body.

Related errors


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