{"record":{"id":"25642b84e7e61495","repo":"Budibase/budibase","slug":"no-refresh-token-found-for-authenticated-user","errorCode":null,"errorMessage":"No refresh token found for authenticated user","messagePattern":"No refresh token found for authenticated user","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/server/src/threads/query.ts","lineNumber":350,"sourceCode":"        queryVerb: query.queryVerb,\n        fields: query.fields,\n        transformer: query.transformer,\n        nullDefaultSupport: query.nullDefaultSupport,\n        ctx: this.ctx,\n        parameters: currentParameters,\n        datasource,\n        queryId,\n      },\n      { noRecursiveQuery: true }\n    ).execute()\n  }\n\n  async refreshOAuth2(ctx: any) {\n    const { oauth2, providerType, _id } = ctx.user\n    const { configId } = ctx.auth\n\n    if (!providerType || !oauth2?.refreshToken) {\n      throw new Error(\"No refresh token found for authenticated user\")\n    }\n\n    const resp = await auth.refreshOAuthToken(\n      oauth2.refreshToken,\n      providerType,\n      configId\n    )\n\n    // Refresh session flow. Should be in same location as refreshOAuthToken\n    // There are several other properties available in 'resp'\n    if (!resp.err) {\n      const globalUserId = getGlobalIDFromUserMetadataID(_id)\n      await auth.updateUserOAuth(globalUserId, resp)\n      if (!this.ctx) {\n        this.ctx = {}\n      }\n      this.ctx.user = (await cache.user.getUser({\n        userId: globalUserId,","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/threads/query.ts#L332-L368","documentation":"When executing an OAuth2-authenticated query whose token has expired, the thread attempts refreshOAuth2 to obtain a new access token using the user's stored refresh token. If the request context has no providerType or the oauth2 object lacks a refreshToken, a plain Error 'No refresh token found for authenticated user' is thrown, so the query cannot be authenticated.","triggerScenarios":"Executing a query against an OAuth2 datasource when ctx.user.oauth2.refreshToken is undefined (user authenticated without a refresh token / token already consumed and not re-stored) or providerType is missing from ctx.user.","commonSituations":"OAuth provider configured without offline access / refresh token scope; refresh token revoked or expired server-side and never refreshed; auth config (configId) changed so stored tokens no longer match; user session created before OAuth2 was configured on the datasource.","solutions":["Re-authenticate the user with the OAuth2 provider so a fresh refresh token is stored, then retry the query","Verify the OAuth2 config requests the offline_access/refresh scope so a refresh token is issued","Check ctx.user.oauth2 and providerType are populated before executing OAuth2 queries; clear stale auth config and re-create it","Confirm the refresh token wasn't revoked in the provider's admin console"],"exampleFix":"// before\nconst resp = await api.executeQueryableQuery(...) // throws: no refresh token\n// after\nif (!ctx.user?.oauth2?.refreshToken) {\n  await reauthenticateUser(configId) // re-run OAuth2 flow to store a refresh token\n}\nconst resp = await api.executeQueryableQuery(...)","handlingStrategy":"try-catch","validationCode":"const { oauth2, providerType } = user\nif (!providerType || !oauth2?.refreshToken) {\n  await reauthenticateUser(user) // run OAuth2 flow to obtain a refresh token\n}","typeGuard":"function hasRefreshToken(user) {\n  return typeof user?.providerType === 'string' && typeof user?.oauth2?.refreshToken === 'string' && user.oauth2.refreshToken.length > 0\n}","tryCatchPattern":"try {\n  await sdk.queries.execute(queryId, params)\n} catch (e) {\n  if (e?.message?.includes('No refresh token found for authenticated user')) {\n    await reauthenticateUser(user) // then retry once\n  } else throw e\n}","preventionTips":["Configure the OAuth2 provider to issue refresh tokens (offline_access scope)","Re-authenticate users when tokens are revoked or config changes","Monitor stored oauth2 tokens for missing refreshToken before executing OAuth2 queries"],"tags":["oauth2","authentication","token-refresh"],"backgroundTag":"oauth-refresh-token-missing","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}