Budibase/budibase · error · Error
Teams OAuth token request failed (${resp.status}): ${await r
Error message
Teams OAuth token request failed (${resp.status}): ${await resp.text()} What it means
getOAuthToken performs an Azure AD client-credentials token request against login.microsoftonline.com using the Teams integration's appId/appPassword. If the HTTP response is not ok, it throws with the status and the raw response body so the Azure AD error (invalid_client, invalid scope, etc.) is visible. Called through the token getter used by both Bot Framework and Graph flows.
Source
Thrown at packages/server/src/escalation/notifications/ms-teams.ts:75
): Promise<string> => {
return cache.withCacheWithDynamicTTL(
cache.CacheKey.OAUTH2_TOKEN(`teams_${msClientId}_${scope}`),
async () => {
const resp = await fetch(
`https://login.microsoftonline.com/${msTenantId}/oauth2/v2.0/token`,
{
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "client_credentials",
client_id: msClientId,
client_secret: appPassword,
scope,
}).toString(),
}
)
if (!resp.ok) {
throw new Error(
`Teams OAuth token request failed (${resp.status}): ${await resp.text()}`
)
}
const data = (await resp.json()) as {
access_token: string
expires_in?: number
}
return { value: data.access_token, ttl: data.expires_in ?? 3600 }
}
)
}
const GRAPH_BASE = "https://graph.microsoft.com/v1.0"
const graphGet = async <T>(url: string, token: string): Promise<T> => {
const resp = await fetch(url, {
headers: { Authorization: `Bearer ${token}` },
})View on GitHub (pinned to a81a902e9a)
Solutions
- Verify the Teams integration's app ID, app password (client secret) and tenant ID match an active Azure AD app registration; regenerate the secret if it expired.
- Check the response body in the error message — Azure returns "invalid_client" for bad credentials or "invalid_scope" for permission issues; fix accordingly.
- Ensure the tenant ID is correct (use the directory/tenant GUID or "common") and that admin consent was granted for the required application permissions.
- Confirm outbound network access to login.microsoftonline.com from the server (proxy/firewall).
Example fix
// before getOAuthToken(clientId, staleSecret, "", MS_SCOPE_BOT) // 400 invalid_client // after getOAuthToken(clientId, rotatedSecret, "00000000-0000-0000-0000-000000000000", MS_SCOPE_BOT)
Defensive patterns
Strategy: try-catch
Validate before calling
if (!clientId || !clientSecret || !tenantId) {
throw new Error("Teams integration requires appId, appPassword and tenantId")
} Try / catch
try {
token = await getOAuthToken(clientId, secret, tenantId, scope)
} catch (err) {
if (err.message.includes("invalid_client")) {
// flag integration credentials as invalid, prompt reconfiguration
} else if (err.message.includes("invalid_scope")) {
// check admin-consented application permissions
} else throw err
} Prevention
- Validate Teams integration credentials (app ID, secret, tenant ID) at save time with a test token request
- Rotate client secrets before expiry and track expiration dates
- Ensure outbound access to login.microsoftonline.com from the server
- Grant admin consent for all required application permissions in Azure AD
When it happens
Trigger: The POST to https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token returns a non-2xx status — typically 400/401 from Azure AD.
Common situations: Wrong or missing msTenantId (e.g. empty because the agent's Teams integration has no tenant configured); wrong appPassword/client secret or a secret that expired or was rotated; app registration deleted; wrong scope requested or permissions not consented by admin; network/proxy blocking login.microsoftonline.com.
Related errors
- Error authenticating with google sheets. ${json.error_descri
- ${err.message}
- Failed to exchange Microsoft OAuth code
- Teams Graph API ${resp.status}: ${await resp.text()}
- Teams Bot API ${resp.status}: ${await resp.text()}
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/d2b00dd51fe46c85.
Report an issue: GitHub.