{"record":{"id":"3503c029d9b38906","repo":"Budibase/budibase","slug":"slack-oauth-client-credentials-are-not-configured","errorCode":null,"errorMessage":"Slack OAuth client credentials are not configured","messagePattern":"Slack OAuth client credentials are not configured","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/api/controllers/ai/agents.ts","lineNumber":600,"sourceCode":"    throw new Error(\"Slack OAuth state is invalid or expired\")\n  }\n\n  const oauthError = String(ctx.query.error || \"\").trim()\n  if (oauthError) {\n    throw new Error(\"Slack OAuth authorization failed\")\n  }\n\n  const code = String(ctx.query.code || \"\").trim()\n  if (!code) {\n    throw new Error(\"Slack OAuth callback is missing the authorization code\")\n  }\n\n  await context.doInWorkspaceContext(statePayload.workspaceId, async () => {\n    const agent = await sdk.ai.agents.getOrThrow(statePayload.agentId)\n    const clientId = agent.slackIntegration?.clientId?.trim()\n    const clientSecret = agent.slackIntegration?.clientSecret?.trim()\n    if (!clientId || !clientSecret) {\n      throw new Error(\"Slack OAuth client credentials are not configured\")\n    }\n\n    const redirectUri = await getSlackOAuthRedirectUrl()\n    const token = await sdk.ai.deployments.slack.exchangeSlackOAuthCode({\n      code,\n      clientId,\n      clientSecret,\n      redirectUri,\n    })\n    const botToken = token.access_token?.trim()\n    if (!botToken) {\n      throw new Error(\"Slack OAuth response did not include a bot token\")\n    }\n\n    const updatedAgent = await sdk.ai.agents.update({\n      ...agent,\n      slackIntegration: {\n        ...agent.slackIntegration,","sourceCodeStart":582,"sourceCodeEnd":618,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/ai/agents.ts#L582-L618","documentation":"Before exchanging the OAuth code, the handler reads clientId and clientSecret from the agent's slackIntegration config. If either is missing/blank it throws this Error — the agent was provisioned without complete Slack client credentials, so the code-for-token exchange with Slack cannot authenticate.","triggerScenarios":"Callback processed for an agent whose slackIntegration lacks clientId or clientSecret — app creation step [193] partially persisted, credentials cleared by an update, or the state payload's agentId points at an agent configured by other means.","commonSituations":"Slack app creation completed but secrets never saved back onto the agent; an agent update overwrote slackIntegration; agent created manually/imported without credentials; doInWorkspaceContext resolving a different agent than intended.","solutions":["Re-run the Slack app creation flow for this agent so clientId/clientSecret are stored on slackIntegration","Verify the agent document in the database has non-empty slackIntegration.clientId and clientSecret","Check that sdk.ai.agents.update after app creation persisted the credentials (no failed write swallowed)","Confirm the state payload references the correct agentId"],"exampleFix":"// before\nslackIntegration: { signingSecret: \"...\" }\n// after\nslackIntegration: { clientId: \"123.456\", clientSecret: \"abc\", signingSecret: \"...\" }","handlingStrategy":"validation","validationCode":"const clientId = agent.slackIntegration?.clientId?.trim()\nconst clientSecret = agent.slackIntegration?.clientSecret?.trim()\nif (!clientId || !clientSecret) {\n  // re-run the Slack app creation flow before allowing OAuth callbacks\n  throw new Error(\"Agent is missing Slack client credentials; recreate the Slack app first\")\n}","typeGuard":"function hasSlackCredentials(s: { clientId?: string; clientSecret?: string } | undefined): s is { clientId: string; clientSecret: string } {\n  return !!s?.clientId?.trim() && !!s?.clientSecret?.trim()\n}","tryCatchPattern":"try {\n  await completeSlackOAuth(ctx)\n} catch (err) {\n  if (err.message.includes(\"client credentials are not configured\")) {\n    // trigger app re-creation for this agent, then ask the user to retry install\n  } else { throw err }\n}","preventionTips":["Verify slackIntegration credentials are persisted immediately after app creation","Guard agent updates so slackIntegration is never overwritten with partial data","Monitor for agents with incomplete slackIntegration documents","Confirm state payloads reference the intended agentId"],"tags":["slack","oauth","credentials","configuration"],"backgroundTag":"missing-oauth-client-credentials","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}