{"record":{"id":"27b6d834aea102a3","repo":"cube-js/cube","slug":"failed-to-get-access-token-res-statustext","errorCode":null,"errorMessage":"Failed to get access token: ${res.statusText}","messagePattern":"Failed to get access token: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"packages/cubejs-databricks-jdbc-driver/src/DatabricksDriver.ts","lineNumber":361,"sourceCode":"  private async fetchAccessToken(): Promise<void> {\n    // Need to exchange client ID + Secret => Access token\n\n    const basicAuth = Buffer.from(`${this.config.properties.OAuth2ClientID}:${this.config.properties.OAuth2Secret}`).toString('base64');\n\n    const res = await fetch(`https://${this.parsedConnectionProperties.host}/oidc/v1/token`, {\n      method: 'POST',\n      headers: {\n        Authorization: `Basic ${basicAuth}`,\n        'Content-Type': 'application/x-www-form-urlencoded',\n      },\n      body: new URLSearchParams({\n        grant_type: 'client_credentials',\n        scope: 'all-apis',\n      }),\n    });\n\n    if (!res.ok) {\n      throw new Error(`Failed to get access token: ${res.statusText}`);\n    }\n\n    const resp = await res.json();\n\n    this.accessToken = resp.access_token;\n    this.accessTokenExpires = Date.now() + resp.expires_in * 1000 - 60_000;\n  }\n\n  private async getValidAccessToken(): Promise<string> {\n    if (\n      !this.accessToken ||\n      !this.accessTokenExpires ||\n      Date.now() >= this.accessTokenExpires\n    ) {\n      await this.fetchAccessToken();\n    }\n    return this.accessToken!;\n  }","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-databricks-jdbc-driver/src/DatabricksDriver.ts#L343-L379","documentation":"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').","triggerScenarios":"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).","commonSituations":"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.","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)"],"exampleFix":"// before\nthrow new Error(`Failed to get access token: ${res.statusText}`);\n// after\nif (!res.ok) {\n  const body = await res.text();\n  throw new Error(`Failed to get access token: ${res.status} ${res.statusText}: ${body}`);\n}","handlingStrategy":"validation","validationCode":"if (!config.clientId || !config.clientSecret) {\n  throw new Error('Databricks OAuth clientId/clientSecret required');\n}\n// verify credentials beforehand:\nconst 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'}) });\nif (!res.ok) console.error('Token check failed', res.status, await res.text());","typeGuard":null,"tryCatchPattern":"try {\n  await driver.query(queryObject);\n} catch (e) {\n  if (String(e.message).startsWith('Failed to get access token')) {\n    // refresh credentials from secret manager, then retry once\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["authentication","oauth","network","http"],"backgroundTag":"oauth-token-request-failed","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}