cube-js/cube · critical

Failed to get access token: ${res.statusText}

Error message

Failed to get access token: ${res.statusText}

What it means

Thrown by fetchAccessToken when the OAuth token endpoint returns a non-OK HTTP response while exchanging client credentials for an access token. The library calls Databricks' token API before opening any connection, so this failure aborts all subsequent queries. res.statusText carries the HTTP reason phrase (e.g. 'Unauthorized').

Source

Thrown at packages/cubejs-databricks-jdbc-driver/src/DatabricksDriver.ts:361

  private async fetchAccessToken(): Promise<void> {
    // Need to exchange client ID + Secret => Access token

    const basicAuth = Buffer.from(`${this.config.properties.OAuth2ClientID}:${this.config.properties.OAuth2Secret}`).toString('base64');

    const res = await fetch(`https://${this.parsedConnectionProperties.host}/oidc/v1/token`, {
      method: 'POST',
      headers: {
        Authorization: `Basic ${basicAuth}`,
        'Content-Type': 'application/x-www-form-urlencoded',
      },
      body: new URLSearchParams({
        grant_type: 'client_credentials',
        scope: 'all-apis',
      }),
    });

    if (!res.ok) {
      throw new Error(`Failed to get access token: ${res.statusText}`);
    }

    const resp = await res.json();

    this.accessToken = resp.access_token;
    this.accessTokenExpires = Date.now() + resp.expires_in * 1000 - 60_000;
  }

  private async getValidAccessToken(): Promise<string> {
    if (
      !this.accessToken ||
      !this.accessTokenExpires ||
      Date.now() >= this.accessTokenExpires
    ) {
      await this.fetchAccessToken();
    }
    return this.accessToken!;
  }

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Verify the OAuth clientId and clientSecret (AuthClientId/AuthSecret or config) match a service principal on the target workspace
  2. Regenerate the client secret if it was rotated or expired in Databricks account console
  3. Confirm the service principal has workspace access and the token endpoint URL/host is correct
  4. Test the token request manually with curl to see the response body (statusText alone hides details)

Example fix

// before
throw new Error(`Failed to get access token: ${res.statusText}`);
// after
if (!res.ok) {
  const body = await res.text();
  throw new Error(`Failed to get access token: ${res.status} ${res.statusText}: ${body}`);
}
Defensive patterns

Strategy: validation

Validate before calling

if (!config.clientId || !config.clientSecret) {
  throw new Error('Databricks OAuth clientId/clientSecret required');
}
// verify credentials beforehand:
const res = await fetch(`https://${host}/oidc/v1/token`, { method: 'POST', headers: {'Content-Type':'application/x-www-form-urlencoded'}, body: new URLSearchParams({grant_type:'client_credentials', client_id: clientId, client_secret: clientSecret, scope:'all-apis'}) });
if (!res.ok) console.error('Token check failed', res.status, await res.text());

Try / catch

try {
  await driver.query(queryObject);
} catch (e) {
  if (String(e.message).startsWith('Failed to get access token')) {
    // refresh credentials from secret manager, then retry once
  }
  throw e;
}

Prevention

When it happens

Trigger: fetchAccessToken (called from getValidAccessToken) POSTs grant_type=client_credentials with scope all-apis to the Databricks OAuth endpoint and Databricks replies with 4xx/5xx status (res.ok false).

Common situations: Wrong clientId/clientSecret in config; credentials from a different workspace/account; service principal without permission to the workspace; expired or rotated secret; network/proxy intercepting with an error page.

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/27b6d834aea102a3. Report an issue: GitHub.