Budibase/budibase · error
No refresh token found for authenticated user
Error message
No refresh token found for authenticated user
What it means
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.
Source
Thrown at packages/server/src/threads/query.ts:350
queryVerb: query.queryVerb,
fields: query.fields,
transformer: query.transformer,
nullDefaultSupport: query.nullDefaultSupport,
ctx: this.ctx,
parameters: currentParameters,
datasource,
queryId,
},
{ noRecursiveQuery: true }
).execute()
}
async refreshOAuth2(ctx: any) {
const { oauth2, providerType, _id } = ctx.user
const { configId } = ctx.auth
if (!providerType || !oauth2?.refreshToken) {
throw new Error("No refresh token found for authenticated user")
}
const resp = await auth.refreshOAuthToken(
oauth2.refreshToken,
providerType,
configId
)
// Refresh session flow. Should be in same location as refreshOAuthToken
// There are several other properties available in 'resp'
if (!resp.err) {
const globalUserId = getGlobalIDFromUserMetadataID(_id)
await auth.updateUserOAuth(globalUserId, resp)
if (!this.ctx) {
this.ctx = {}
}
this.ctx.user = (await cache.user.getUser({
userId: globalUserId,View on GitHub (pinned to a81a902e9a)
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
Example fix
// before
const resp = await api.executeQueryableQuery(...) // throws: no refresh token
// after
if (!ctx.user?.oauth2?.refreshToken) {
await reauthenticateUser(configId) // re-run OAuth2 flow to store a refresh token
}
const resp = await api.executeQueryableQuery(...) Defensive patterns
Strategy: try-catch
Validate before calling
const { oauth2, providerType } = user
if (!providerType || !oauth2?.refreshToken) {
await reauthenticateUser(user) // run OAuth2 flow to obtain a refresh token
} Type guard
function hasRefreshToken(user) {
return typeof user?.providerType === 'string' && typeof user?.oauth2?.refreshToken === 'string' && user.oauth2.refreshToken.length > 0
} Try / catch
try {
await sdk.queries.execute(queryId, params)
} catch (e) {
if (e?.message?.includes('No refresh token found for authenticated user')) {
await reauthenticateUser(user) // then retry once
} else throw e
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Error getting account by email ${email}
- Authentication failed with Microsoft Graph. Verify SharePoin
- ${err.message}
- invalid_api_key
- Password change is disabled for this user
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/25642b84e7e61495.
Report an issue: GitHub.