mastra-ai/mastra · critical

SlackIntegration: 'signingSecret' is required — Slack cannot

Error message

SlackIntegration: 'signingSecret' is required — Slack cannot verify inbound requests without it.

What it means

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.

Source

Thrown at mastracode/factory/src/integrations/slack/integration.ts:119

  readonly id = 'slack';
  /**
   * The OIDC connect flow round-trips a signed `state` through Slack, so the
   * replica handling the callback must be able to verify a state a different
   * replica signed.
   */
  readonly requiresStableStateSigner = true;

  readonly #config: SlackIntegrationConfig;
  /**
   * Whether `channels()` found a source-control owner on the context and wired
   * repo-backed sessions. Set at the channels() attach path, which runs once at
   * boot before diagnostics are served.
   */
  #repoBackedSessions = false;

  constructor(config: SlackIntegrationConfig) {
    if (!config.signingSecret) {
      throw new Error(
        "SlackIntegration: 'signingSecret' is required — Slack cannot verify inbound requests without it.",
      );
    }
    this.#config = config;
  }

  channels(ctx: IntegrationContext): FactoryChannelsConfig {
    // Repo-backed sessions come from the factory's source-control owner
    // (GitHub, when registered) — no config-level wiring by the entry.
    const sourceControlOwner = ctx.storage.sourceControlOwner;
    this.#repoBackedSessions = Boolean(sourceControlOwner);
    return createSlackChannelsConfig({
      slack: {
        clientId: this.#config.clientId,
        clientSecret: this.#config.clientSecret,
        signingSecret: this.#config.signingSecret,
        botToken: this.#config.botToken,
      },

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Copy the Signing Secret from Slack app settings → Basic Information → App Credentials and pass it as `signingSecret`.
  2. Set the SLACK_SIGNING_SECRET env var in the deployment environment (not just locally).
  3. Add a boot-time check that fails with a clear message if the env var is empty before constructing the integration.
  4. Do not substitute the Bot Token (xoxb-...) — the Signing Secret is a separate credential.

Example fix

// before
new SlackIntegration({ signingSecret: process.env.SLACK_SIGNING_SECRET, ... }); // env unset => undefined
// after
const signingSecret = process.env.SLACK_SIGNING_SECRET;
if (!signingSecret) throw new Error('SLACK_SIGNING_SECRET is not set');
new SlackIntegration({ signingSecret, ... });
Defensive patterns

Strategy: validation

Validate before calling

const signingSecret = process.env.SLACK_SIGNING_SECRET;
if (!signingSecret) {
  throw new Error('SLACK_SIGNING_SECRET env var is missing; copy it from Slack app settings → Basic Information.');
}
new SlackIntegration({ signingSecret, ... });

Type guard

function hasSigningSecret(c: SlackIntegrationConfig): c is SlackIntegrationConfig & { signingSecret: string } {
  return typeof c.signingSecret === 'string' && c.signingSecret.length > 0;
}

Try / catch

let integration: SlackIntegration;
try {
  integration = new SlackIntegration(config);
} catch (err) {
  if (err instanceof Error && err.message.includes("'signingSecret' is required")) {
    console.error('Boot failed: provision SLACK_SIGNING_SECRET before starting.');
    process.exit(1);
  }
  throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/f14c33e7672747ce. Report an issue: GitHub.