slackapi/bolt-js

Open Modal API is not working suddenly. And error message is `Error: An API error occurred: invalid_trigger_id`.

Closed this issue · 9 comments

Open Modal API is not working suddenly.

I am building two slack app.
One is for release environment. And other one is for development environment.
They have deploying same code.

One day, Open Modal API is not working suddenly.
And error message is Error: An API error occurred: invalid_trigger_id.

Reproducible in:

The Slack SDK version

{
  "name": "nest-typescript-starter",
  "private": true,
  "version": "1.0.0",
  "description": "Nest TypeScript starter repository",
  "license": "MIT",
  "scripts": {
    "hash": "node hash.js",
    "prebuild": "rimraf dist",
    "build": "nest build --webpack",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "export NODE_ENV='dev' && nest start",
    "start:dev": "export NODE_ENV='dev' && nest start --watch",
    "start:debug": "export NODE_ENV='dev' && nest start --debug --watch",
    "start:pre": "export NODE_ENV='pre' && node dist/main",
    "start:prod": "node dist/main",
    "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json"
  },
  "dependencies": {
    "@nestjs/common": "^9.0.0",
    "@nestjs/config": "^2.2.0",
    "@nestjs/core": "^9.0.0",
    "@nestjs/platform-express": "^9.0.0",
    "@nestjs/typeorm": "^9.0.1",
    "@slack/bolt": "3.12.2",
    "axios": "^1.1.3",
    "dotenv": "^16.0.3",
    "express": "^4.18.2",
    "fs-extra": "11.1.1",
    "i18n": "^0.15.1",
    "lodash-es": "4.17.21",
    "mysql": "^2.18.1",
    "nestjs-pino": "^3.1.1",
    "pino-http": "^8.2.1",
    "pino-pretty": "9.1.1",
    "pkg": "5.8.1",
    "reflect-metadata": "^0.1.13",
    "rxjs": "^7.5.5",
    "simple-git": "3.20.0",
    "typeorm": "^0.3.10"
  },
  "bin": "dist/main.js",
  "pkg": {
    "assets": "node_modules/**/*.*"
  },
  "devDependencies": {
    "@nestjs/cli": "9.5.0",
    "@nestjs/schematics": "^9.0.0",
    "@nestjs/testing": "^9.0.0",
    "@types/express": "^4.17.13",
    "@types/node": "^18.11.9",
    "@types/webpack-env": "^1.18.0",
    "@typescript-eslint/eslint-plugin": "^5.30.5",
    "@typescript-eslint/parser": "^5.30.5",
    "eslint": "^8.19.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-prettier": "^4.2.1",
    "prettier": "^2.7.1",
    "source-map-support": "^0.5.21",
    "ts-loader": "^9.3.1",
    "ts-node": "^10.8.2",
    "tsconfig-paths": "^4.0.0",
    "typescript": "^4.7.4"
  },
  "jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".*\\.spec\\.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "collectCoverageFrom": [
      "**/*.(t|j)s"
    ],
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  }
}

Node.js runtime version

v16.13.1

OS info

(Paste the output of sw_vers && uname -v on macOS/Linux or ver on Windows OS)

Steps to reproduce:

(Share the commands to run, source code, and project settings)

  1. App initiated
export const boltApp = new App({
  receiver,
  signingSecret: getEnv('SLACK_SIGNING_SECRET'),
  clientId: getEnv('SLACK_CLIENT_ID'),
  clientSecret: getEnv('SLACK_CLIENT_SECRET'),
  // stateSecret: 'my-secret',
  appToken: getEnv('SLACK_APP_TOKEN'),
  scopes: ['commands', 'chat:write', 'app_mentions:read'],
  logLevel: LogLevel.INFO,
});

let app: INestApplication
registerListeners(boltApp)
  1. Add commands
const allowAction = ['login', 'logout', 'help', 'notify']
const actionMap = {
  'login': loginCommandCallback,
  'logout': logoutCommandCallback,
  'help': helpCommandCallback,
  'notify': notifyCommandCallback
}

const onesCommandCallback = async ({ ack, command, respond, ...rest }:
  AllMiddlewareArgs & SlackCommandMiddlewareArgs) => {
  try {
    const param = command?.text
    const firParam = param?.split(' ')?.[0]
    const onesUser = await findOnesUserBySlackUserId(rest.body.user_id)
    console.log(firParam, rest.body.user_id, 'user_id');
    if (allowAction.includes(firParam)) {
      actionMap[firParam]({ack, command, respond, ...rest}, onesUser)
    }else {

      await ack();
      await respond({
        ...commandBlocks.errorCmdBlocks
      });
    }
  } catch (error) {
    console.error(error);
  }
};

app.command('/preview-ones', onesCommandCallback);
  1. Login action
export const loginAction = async ({ ack, payload, client, body, respond }: AllMiddlewareArgs & SlackActionMiddlewareArgs
) => {
  try {

    const user_id = body?.user?.id
    await ack();
    const onesUser = await findOnesUserBySlackUserId(user_id)
    if (onesUser) {
      const res = await respond({
        text: `You’ve logged in as ${onesUser?.email}`,
      })
    } else {
      const result = await client.views.open({
        trigger_id: (<BlockAction>body).trigger_id,
        view: {
          "title": {
            "type": "plain_text",
            "text": "Log in",
            "emoji": true
          },
          "type": "modal",
          "close": {
            "type": "plain_text",
            "text": "Cancel",
            "emoji": true
          },
          "blocks": [
            {
              "type": "section",
              "text": {
                "type": "mrkdwn",
                "text": "To use <https://ones.com/|ONES.com>, please login to your <https://ones.com/|ONES.com> account and authorize your Slack to create a connection. <https://docs.ones.com/integrations/slack-and-ones|Learn more>"
              }
            },
            {
              "type": "actions",
              "elements": [
                {
                  "type": "button",
                  "text": {
                    "type": "plain_text",
                    "text": "Log in",
                    "emoji": true
                  },
                  "action_id": actionMap.action_empty_response,
                  "style": "primary",
                  "url": `${getEnv('ONES_HOST')}/app/slack/slack/install`,
                }
              ]
            }
          ]
        }
      })
    }
  } catch (error) {
    console.error(error);
    respond(errBlocks)
  }
};

Expected result:

Open a modal when I click the Log in button.

image

Actual result:

Nothing happens.

image image

Requirements

For general questions/issues about Slack API platform or its server-side, could you submit questions at https://my.slack.com/help/requests/new instead. 🙇

Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you are agreeing to those rules.

How does the loginAction get invoked?

invalid_trigger_id is returned if the trigger id is not in a valid format, meaning, the string if malformed. Have you checked the trigger ID string to verify it looks correct? See the views.open Errors section for details on invalid_trigger_id.

Here is the source code about loginAction get invoked.

  1. First, new App. And registerListeners.
import { App } from '@slack/bolt';
import registerListeners from './slack-listeners'

export const boltApp = new App({
  receiver,
  signingSecret: getEnv('SLACK_SIGNING_SECRET'),
  clientId: getEnv('SLACK_CLIENT_ID'),
  clientSecret: getEnv('SLACK_CLIENT_SECRET'),
  // stateSecret: 'my-secret',
  appToken: getEnv('SLACK_APP_TOKEN'),
  scopes: ['commands', 'chat:write', 'app_mentions:read'],
  logLevel: LogLevel.INFO,
});

registerListeners(boltApp)
  1. Details about registerListeners. Register actions and commands.
import { App } from '@slack/bolt';
import actions from './actions';
import commands from './commands';

const registerListeners = (app: App) => {
  actions.register(app);
  commands.register(app);
};

export default registerListeners;
  1. Details about actions.
import { App } from '@slack/bolt';
import { AllMiddlewareArgs, BlockAction, SlackActionMiddlewareArgs } from '@slack/bolt';
import { loginAction } from './common';
import { actionMap } from './config' // Map of string

const register = (app: App) => {
  app.action(actionMap.action_login, loginAction);
};

export default { register };
  1. Details about loginAction.
export const loginAction = async ({ ack, payload, client, body, respond }: AllMiddlewareArgs & SlackActionMiddlewareArgs
) => {
  try {

    const user_id = body?.user?.id
    await ack();
    const onesUser = await findOnesUserBySlackUserId(user_id)
    if (onesUser) {
      const res = await respond({
        text: `You’ve logged in as ${onesUser?.email}`,
      })
    } else {
      const result = await client.views.open({
        trigger_id: (<BlockAction>body).trigger_id,
        view: {
          "title": {
            "type": "plain_text",
            "text": "Log in",
            "emoji": true
          },
          "type": "modal",
          "close": {
            "type": "plain_text",
            "text": "Cancel",
            "emoji": true
          },
          "blocks": [
            {
              "type": "section",
              "text": {
                "type": "mrkdwn",
                "text": "To use <https://ones.com/|ONES.com>, please login to your <https://ones.com/|ONES.com> account and authorize your Slack to create a connection. <https://docs.ones.com/integrations/slack-and-ones|Learn more>"
              }
            },
            {
              "type": "actions",
              "elements": [
                {
                  "type": "button",
                  "text": {
                    "type": "plain_text",
                    "text": "Log in",
                    "emoji": true
                  },
                  "action_id": actionMap.action_empty_response,
                  "style": "primary",
                  "url": `${getEnv('ONES_HOST')}/app/slack/slack/install`,
                }
              ]
            }
          ]
        }
      })
    }
  } catch (error) {
    console.error(error);
    respond(errBlocks)
  }
};

  1. When I send login command. It could render a message block as usually.
image
  1. And then, I click the Log in button. There is an error happened.
image
  1. I print the error message from catch context.
`##${(body as any).trigger_id}##${typeof (body as any).trigger_id}##` // template string like this

So, I think the trigger_id is 6951794901890.6062745778723.40f68b59d1718d3a566481116db507aa.

And, I think that it comes from @slack/bolt.

BTW, we used Slack Pro before. And we built these two Apps (same code for different environment).
And, our Slack Pro has got expired since last month.
I am wondering that if this problem cause by the version reason?

The trigger ID looks to be in a correct format. It comes from the block-actions event payload that Slack issues to your app: it is generated when a user clicks e.g. a button, and is a kind of time-limited key that unlocks certain APIs (like views.open), ensuring apps respond in a timely manner to user interactions.

Is the app you are seeing this error with installed to only one workspace, or to multiple? And the workspace you are seeing the error in, is that the workspace you recently downgraded?

I think we will have to escalate this inquiry for further investigation as I am not sure why you would receive this error. If you can, please send an email to feedback@slack.com, and provide them a link to this issue with a brief description of your problem. Also please provide them with the workspace/team/org IDs that you are seeing this error in, and the app ID. This will allow our customer support team to investigate production Slack logs related to your app.

I realized that the trigger ID is valid in a short time.
And I printed the timestamp also.
The log result shown as 0~3ms.
image

I installed it in two workspace.
And I can see this error in these two workspace.
I can see some tips about Pro version in the top.
And our group downgraded at 2 months ago.

image image image image

Yeah, I already sent an email to feedback@slack.com.

It takes a long time to troubleshoot.
Finally, it is a environment mistake in the application management config about the events link.

So, it was solved.

Just for future reference, could you elaborate on what this means?

It is a environment mistake in the application management config about the events link.

@lixinliang Thank you for sharing your issue.

Perhaps I'm running into this same error. Can you tell me how you solved it?

We look forward to your reply.