{"record":{"id":"f14c33e7672747ce","repo":"mastra-ai/mastra","slug":"slackintegration-signingsecret-is-required-sl","errorCode":null,"errorMessage":"SlackIntegration: 'signingSecret' is required — Slack cannot verify inbound requests without it.","messagePattern":"SlackIntegration: 'signingSecret' is required — Slack cannot verify inbound requests without it\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"mastracode/factory/src/integrations/slack/integration.ts","lineNumber":119,"sourceCode":"  readonly id = 'slack';\n  /**\n   * The OIDC connect flow round-trips a signed `state` through Slack, so the\n   * replica handling the callback must be able to verify a state a different\n   * replica signed.\n   */\n  readonly requiresStableStateSigner = true;\n\n  readonly #config: SlackIntegrationConfig;\n  /**\n   * Whether `channels()` found a source-control owner on the context and wired\n   * repo-backed sessions. Set at the channels() attach path, which runs once at\n   * boot before diagnostics are served.\n   */\n  #repoBackedSessions = false;\n\n  constructor(config: SlackIntegrationConfig) {\n    if (!config.signingSecret) {\n      throw new Error(\n        \"SlackIntegration: 'signingSecret' is required — Slack cannot verify inbound requests without it.\",\n      );\n    }\n    this.#config = config;\n  }\n\n  channels(ctx: IntegrationContext): FactoryChannelsConfig {\n    // Repo-backed sessions come from the factory's source-control owner\n    // (GitHub, when registered) — no config-level wiring by the entry.\n    const sourceControlOwner = ctx.storage.sourceControlOwner;\n    this.#repoBackedSessions = Boolean(sourceControlOwner);\n    return createSlackChannelsConfig({\n      slack: {\n        clientId: this.#config.clientId,\n        clientSecret: this.#config.clientSecret,\n        signingSecret: this.#config.signingSecret,\n        botToken: this.#config.botToken,\n      },","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/integrations/slack/integration.ts#L101-L137","documentation":"The SlackIntegration constructor requires `config.signingSecret` because Slack sends signed requests (x-slack-signature header) that must be verified with the app's Signing Secret from the Slack app settings. Without it the integration cannot authenticate that inbound HTTP requests genuinely come from Slack, so it refuses to construct rather than serving an insecure endpoint.","triggerScenarios":"Calling `new SlackIntegration(config)` with `signingSecret` undefined, null, or an empty string — typically when it is read from env (`process.env.SLACK_SIGNING_SECRET`) and that variable is unset or blank.","commonSituations":"Deploying to an environment where the secret was never provisioned (missing .env, secrets manager not mounted); renaming the env var in code but not in the deployment; copying config from a Slack app where only the Bot Token was configured.","solutions":["Copy the Signing Secret from Slack app settings → Basic Information → App Credentials and pass it as `signingSecret`.","Set the SLACK_SIGNING_SECRET env var in the deployment environment (not just locally).","Add a boot-time check that fails with a clear message if the env var is empty before constructing the integration.","Do not substitute the Bot Token (xoxb-...) — the Signing Secret is a separate credential."],"exampleFix":"// before\nnew SlackIntegration({ signingSecret: process.env.SLACK_SIGNING_SECRET, ... }); // env unset => undefined\n// after\nconst signingSecret = process.env.SLACK_SIGNING_SECRET;\nif (!signingSecret) throw new Error('SLACK_SIGNING_SECRET is not set');\nnew SlackIntegration({ signingSecret, ... });","handlingStrategy":"validation","validationCode":"const signingSecret = process.env.SLACK_SIGNING_SECRET;\nif (!signingSecret) {\n  throw new Error('SLACK_SIGNING_SECRET env var is missing; copy it from Slack app settings → Basic Information.');\n}\nnew SlackIntegration({ signingSecret, ... });","typeGuard":"function hasSigningSecret(c: SlackIntegrationConfig): c is SlackIntegrationConfig & { signingSecret: string } {\n  return typeof c.signingSecret === 'string' && c.signingSecret.length > 0;\n}","tryCatchPattern":"let integration: SlackIntegration;\ntry {\n  integration = new SlackIntegration(config);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"'signingSecret' is required\")) {\n    console.error('Boot failed: provision SLACK_SIGNING_SECRET before starting.');\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["Fail at process startup if SLACK_SIGNING_SECRET is absent, before any construction.","Keep the Signing Secret and Bot Token in separate, clearly named env vars.","Add the var to deployment/secret-manager checklists for every environment."],"tags":["slack","configuration","authentication","missing-secret"],"backgroundTag":"missing-env-var","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}