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
- Verify the OAuth clientId and clientSecret (AuthClientId/AuthSecret or config) match a service principal on the target workspace
- Regenerate the client secret if it was rotated or expired in Databricks account console
- Confirm the service principal has workspace access and the token endpoint URL/host is correct
- 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
- Store clientId/secret in a secret manager and rotate deliberately
- Grant the service principal workspace access before wiring it into Cube
- Pre-validate the token endpoint with curl during setup
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
- ${response.status === 401 ? 'Unauthorized request' : 'Unexpe
- HTTP error! status: ${response.status}
- unexpected response ${response.statusText}
- HTTP ${response.status}: ${response.statusText}
- Databricks API error: ${res.statusText}
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/27b6d834aea102a3.
Report an issue: GitHub.