Budibase/budibase · error · Error

Slack OAuth callback is missing the authorization code

Error message

Slack OAuth callback is missing the authorization code

What it means

On a successful (non-error) callback, Slack returns ?code=... which is exchanged for a bot token. If the code parameter is missing or empty despite no error being present, the handler throws this Error because the token exchange cannot proceed.

Source

Thrown at packages/server/src/api/controllers/ai/agents.ts:592

  }

  const cacheKey = getSlackOAuthStateCacheKey(state)
  const statePayload = (await cache.get(cacheKey, {
    useTenancy: false,
  })) as SlackOAuthState | undefined
  await cache.destroy(cacheKey, { useTenancy: false })
  if (!statePayload?.agentId || !statePayload.workspaceId) {
    throw new Error("Slack OAuth state is invalid or expired")
  }

  const oauthError = String(ctx.query.error || "").trim()
  if (oauthError) {
    throw new Error("Slack OAuth authorization failed")
  }

  const code = String(ctx.query.code || "").trim()
  if (!code) {
    throw new Error("Slack OAuth callback is missing the authorization code")
  }

  await context.doInWorkspaceContext(statePayload.workspaceId, async () => {
    const agent = await sdk.ai.agents.getOrThrow(statePayload.agentId)
    const clientId = agent.slackIntegration?.clientId?.trim()
    const clientSecret = agent.slackIntegration?.clientSecret?.trim()
    if (!clientId || !clientSecret) {
      throw new Error("Slack OAuth client credentials are not configured")
    }

    const redirectUri = await getSlackOAuthRedirectUrl()
    const token = await sdk.ai.deployments.slack.exchangeSlackOAuthCode({
      code,
      clientId,
      clientSecret,
      redirectUri,
    })
    const botToken = token.access_token?.trim()

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Restart the OAuth flow from initiation — authorization codes are single-use and short-lived
  2. Verify the Slack app's redirect URL matches exactly and does not get rewritten by proxies
  3. Ensure the authorize URL requests the expected response_type=code flow
  4. Log the full callback query server-side to see what Slack actually returned
Defensive patterns

Strategy: validation

Validate before calling

const url = new URL(callbackUrl)
if (!url.searchParams.get("error") && !url.searchParams.get("code")) {
  throw new Error("Callback has neither code nor error — restart the OAuth flow")
}

Type guard

function hasOAuthCode(q: Record<string, unknown>): q is Record<string, string> & { code: string } {
  return typeof q.code === "string" && q.code.trim() !== ""
}

Try / catch

try {
  await completeSlackOAuth(ctx)
} catch (err) {
  if (err.message.includes("missing the authorization code")) {
    // restart flow; codes are single-use so retrying the callback never works
  } else { throw err }
}

Prevention

When it happens

Trigger: Callback arrives with neither error nor code — truncated redirect URL, duplicate query handling, Slack returning an unexpected redirect shape, or the user re-submitting a callback whose code was already consumed/stripped.

Common situations: Proxies rewriting the redirect and dropping query params; users re-opening a callback URL from history after the code was used; misconfigured redirect URL in the Slack app settings.

Related errors


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