Budibase/budibase · error

Error getting account by email ${email}

Error message

Error getting account by email ${email}

What it means

fetchSharePointSitesByDatasourceAuthConfig lists SharePoint sites using an OAuth2 client-credentials bearer token. When the initial Graph /sites call returns 401, it clears the cached token and retries once; if the retry also returns 401, this HTTPError (400) is thrown. It means the tenant/client credentials themselves cannot authenticate to Microsoft Graph, not just a stale token.

Source

Thrown at packages/backend-core/src/accounts/accounts.ts:33

export const getAccount = async (
  email: string
): Promise<CloudAccount | undefined> => {
  if (EXIT_EARLY) {
    return
  }
  const payload = {
    email,
  }
  const response = await api.post(`/api/accounts/search`, {
    body: payload,
    headers: {
      [Header.API_KEY]: env.ACCOUNT_PORTAL_API_KEY,
    },
  })

  if (response.status !== 200) {
    throw new Error(`Error getting account by email ${email}`)
  }

  const json: CloudAccount[] = await response.json()
  return json[0]
}

export const getAccountByTenantId = async (
  tenantId: string
): Promise<CloudAccount | undefined> => {
  if (EXIT_EARLY) {
    return
  }
  const payload = {
    tenantId,
  }
  const response = await api.post(`/api/accounts/search`, {
    body: payload,
    headers: {

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Verify the client ID, client secret, and token URL in the datasource's OAuth2 client-credentials auth config against the Azure app registration.
  2. In Azure Portal, confirm the app registration secret is not expired and the app is enabled in the correct tenant.
  3. Confirm the app has SharePoint application permissions (Sites.Read.All or similar) and admin consent granted, then re-run the site listing.
  4. Regenerate the client secret and update the auth config, then retry.

Example fix

// before
"authConfig": { "method": "post", "url": "https://login.microsoftonline.com/old-tenant/oauth2/v2.0/token", "clientId": "old-id", "clientSecret": "expired-secret", "scope": "https://graph.microsoft.com/.default" }
// after
"authConfig": { "method": "post", "url": "https://login.microsoftonline.com/<correct-tenant-id>/oauth2/v2.0/token", "clientId": "<correct-client-id>", "clientSecret": "<newly-generated-secret>", "scope": "https://graph.microsoft.com/.default" }
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check the auth config before calling
const config = datasource.config?.authConfigs?.find(c => c._id === authConfigId)
if (!config?.clientId || !config?.clientSecret || !config?.url) {
  throw new Error("SharePoint OAuth2 client credentials are incomplete")
}

Try / catch

try {
  await fetchSharePointSitesByDatasourceAuthConfig(datasourceId, authConfigId)
} catch (e) {
  if (String(e.message).includes("Authentication failed with Microsoft Graph")) {
    // surface a config-repair prompt: client ID/secret/tenant are wrong
  } else throw e
}

Prevention

When it happens

Trigger: getSharePointBearerToken or fetchSharePointSitesByAppToken throws an error with status 401, cleanStoredTokensForAuthConfig runs, a fresh token is fetched, and the retried /sites?search=* call returns 401 again.

Common situations: Wrong clientSecret in the OAuth2 client-credentials auth config; app registration deleted or disabled; tenant ID / token URL pointing at the wrong tenant; client credentials flow disabled or app blocked by conditional access; expired client secret in Azure AD.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/f70b5ea1413b2ce3. Report an issue: GitHub.