{"record":{"id":"2af99021f202e5e7","repo":"Budibase/budibase","slug":"slack-integration-requires-bottoken-and-signingsec","errorCode":null,"errorMessage":"Slack integration requires botToken and signingSecret","messagePattern":"Slack integration requires botToken and signingSecret","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/deployments/slack.ts","lineNumber":60,"sourceCode":"  return truncate(safeName || \"budibase-agent\", MAX_BOT_DISPLAY_NAME_LENGTH)\n}\n\nexport const validateSlackIntegration = (\n  agent: Agent\n): ResolvedSlackIntegration => {\n  const integration = agent.slackIntegration\n  if (!integration) {\n    throw new HTTPError(\n      \"Slack integration is not configured for this agent\",\n      400\n    )\n  }\n\n  const botToken = integration.botToken?.trim()\n  const signingSecret = integration.signingSecret?.trim()\n\n  if (!botToken || !signingSecret) {\n    throw new HTTPError(\n      \"Slack integration requires botToken and signingSecret\",\n      400\n    )\n  }\n\n  return {\n    botToken,\n    signingSecret,\n  }\n}\n\nexport const buildSlackWebhookUrl = async (agentId: string) =>\n  await shared.buildProviderWebhookUrl(AgentChannelProvider.SLACK, agentId)\n\nexport const buildSlackManifest = ({\n  agent,\n  messagingEndpointUrl,\n  oauthRedirectUrl,","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/deployments/slack.ts#L42-L78","documentation":"This HTTP 400 error is thrown by validateSlackIntegration when the agent has a slackIntegration object but either botToken or signingSecret is missing or blank after trimming. Both credentials are required: the bot token authenticates Slack API calls and the signing secret verifies incoming Slack webhook requests.","triggerScenarios":"Saving/deploying an agent whose slackIntegration contains botToken or signingSecret set to null, undefined, whitespace-only strings, or empty strings - e.g. a form that was submitted with only one of the two credentials filled in.","commonSituations":"User pasted the bot token but forgot the signing secret (or vice versa); environment variable interpolation produced empty strings; a partial agent update overwrote one credential with null; secrets were redacted by an export/import round-trip.","solutions":["Set both botToken (xoxb-... Slack bot token) and signingSecret in the agent's slackIntegration and save again.","Check the Slack app settings: bot token from 'OAuth & Permissions', signing secret from 'Basic Information > App Credentials'.","Confirm the values are non-empty after trimming - inspect for whitespace-only or undefined values in the saved agent document.","If secrets come from env vars, verify they are present in the deployment environment and not empty at runtime."],"exampleFix":"// before\nagent.slackIntegration = { botToken: \"xoxb-123-456-abcdef\", signingSecret: \"   \" } // trimmed to empty\n// after\nagent.slackIntegration = {\n  botToken: process.env.SLACK_BOT_TOKEN,\n  signingSecret: process.env.SLACK_SIGNING_SECRET\n}","handlingStrategy":"validation","validationCode":"const botToken = integration.botToken?.trim()\nconst signingSecret = integration.signingSecret?.trim()\nif (!botToken || !signingSecret) {\n  throw new Error(\"Both botToken and signingSecret must be set (non-blank) in slackIntegration\")\n}","typeGuard":"const hasSlackCredentials = (i: { botToken?: string; signingSecret?: string }): i is { botToken: string; signingSecret: string } =>\n  typeof i.botToken === \"string\" && i.botToken.trim() !== \"\" &&\n  typeof i.signingSecret === \"string\" && i.signingSecret.trim() !== \"\"","tryCatchPattern":"try {\n  await deployAgentToSlack(agent)\n} catch (e) {\n  if (e instanceof HTTPError && e.message.includes(\"botToken and signingSecret\")) {\n    // re-collect both credentials from the user\n  }\n  throw e\n}","preventionTips":["Require both fields in the settings form (non-empty validation before submit).","Source credentials from env/secret manager and log a startup warning if either is unset.","Avoid partial PATCH updates that can null out one credential while setting the other."],"tags":["validation","slack","credentials"],"backgroundTag":"missing-credentials","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}