{"record":{"id":"452995d97e93f11d","repo":"mem0ai/mem0","slug":"databricks-vector-store-requires-clientid-clientse","errorCode":null,"errorMessage":"Databricks vector store requires clientId/clientSecret for OAuth token refresh.","messagePattern":"Databricks vector store requires clientId/clientSecret for OAuth token refresh\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mem0-ts/src/oss/src/vector_stores/databricks.ts","lineNumber":974,"sourceCode":"        this.fullIndexName,\n        \"WriteVectorIndex\",\n      );\n    }\n\n    return undefined;\n  }\n\n  private async getOAuthAccessToken(\n    authorizationDetails?: string,\n  ): Promise<string> {\n    const cacheKey = authorizationDetails || \"__management__\";\n    const cached = this.oauthTokens.get(cacheKey);\n    if (cached && Date.now() < cached.expiresAt - 60_000) {\n      return cached.accessToken;\n    }\n\n    if (!this.clientId || !this.clientSecret) {\n      throw new Error(\n        \"Databricks vector store requires clientId/clientSecret for OAuth token refresh.\",\n      );\n    }\n\n    const formData = new URLSearchParams({\n      grant_type: \"client_credentials\",\n      scope: \"all-apis\",\n    });\n    if (authorizationDetails) {\n      formData.set(\"authorization_details\", authorizationDetails);\n    }\n\n    const response = await axios.post(\n      `${this.workspaceUrl}/oidc/v1/token`,\n      formData,\n      {\n        auth: {\n          username: this.clientId,","sourceCodeStart":956,"sourceCodeEnd":992,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0-ts/src/oss/src/vector_stores/databricks.ts#L956-L992","documentation":"getOAuthAccessToken() mints and refreshes OAuth tokens for service-principal auth. When the cached token has expired (or no token exists for the scope) it must call the token endpoint, which fundamentally requires clientId/clientSecret. If they are absent — e.g. the store was built with a custom httpClient and no service-principal credentials — refresh throws.","triggerScenarios":"Constructing the store with an httpClient or an initially valid token but no clientId/clientSecret, then running long enough for a cached token to expire (past expiresAt - 60s) so a refresh is attempted.","commonSituations":"Long-lived servers using OAuth initially but config later changed to PAT-only; injecting a mock httpClient in tests while production config lacks service-principal credentials; expired token cache after Databricks rotates keys.","solutions":["Provide clientId and clientSecret in the config so token refresh can work","Or switch to a long-lived accessToken (PAT) if token rotation is not desired — though PATs expire too and must be rotated manually","Or supply your own httpClient that handles auth headers and refresh externally"],"exampleFix":"// before\nnew Databricks({ host, httpClient: myClient }); // no SP credentials\n\n// after\nnew Databricks({ host, clientId: process.env.DBX_CLIENT_ID!, clientSecret: process.env.DBX_CLIENT_SECRET! });","handlingStrategy":"validation","validationCode":"if (usingOauth && !(cfg.clientId && cfg.clientSecret)) {\n  throw new Error('Long-running OAuth usage requires clientId/clientSecret for refresh');\n}","typeGuard":null,"tryCatchPattern":"try { await store.search(q, 5); } catch (e) { if (e instanceof Error && e.message.includes('clientId/clientSecret for OAuth token refresh')) { /* switch to PAT or add SP credentials */ } throw e; }","preventionTips":["For long-lived processes, always configure service-principal credentials, not one-shot tokens","Alert on auth errors so credential expiry is visible before it becomes an outage"],"tags":["databricks","oauth","authentication","configuration"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}