使用SAM部署@slack/bolt至AWS Lambda时遇类型错误求助
问题解决方案
错误原因分析
Cannot convert undefined or null to object:
该错误来自AwsLambdaReceiver.getHeaderValue方法,说明传入的事件对象event.headers为null或undefined。同时你的Lambda处理程序在每次请求时都调用awsLambdaReceiver.start(),这会导致接收器重复初始化,引发内部状态异常。Wrong arguments:
你的lambdaHandler是异步函数,但同时使用了callback参数,这与Node.js 18.x Lambda运行时的异步处理逻辑冲突,导致运行时无法正确处理返回值。
修复步骤
1. 修正Lambda处理程序代码(app.mjs)
将接收器初始化和启动移到函数外部,避免重复初始化;移除callback参数,改用异步函数的返回值:
import pkg from '@slack/bolt'; const { App, AwsLambdaReceiver } = pkg; // 初始化接收器(仅执行一次) const awsLambdaReceiver = new AwsLambdaReceiver({ signingSecret: process.env.SLACK_SIGNING_SECRET, // 使用环境变量,不要硬编码 }); const app = new App({ token: process.env.SLACK_BOT_TOKEN, // 使用环境变量 receiver: awsLambdaReceiver, }); // 消息监听逻辑不变 app.message('hello', async ({ message, say }) => { await say({ blocks: [ { "type": "section", "text": { "type": "mrkdwn", "text": `Hey there <@${message.user}>!` }, "accessory": { "type": "button", "text": { "type": "plain_text", "text": "Click Me" }, "action_id": "button_click" } } ], text: `Hey there <@${message.user}>!` }); }); app.action('button_click', async ({ body, ack, say }) => { await ack(); await say(`<@${body.user.id}> clicked the button`); }); // 启动接收器(仅冷启动时执行一次) const handler = await awsLambdaReceiver.start(); // 修正后的Lambda处理程序 export const lambdaHandler = async (event, context) => { // 禁用Lambda回调上下文,确保异步处理正确 context.callbackWaitsForEmptyEventLoop = false; return handler(event, context); };
2. 修复SAM模板(template.yaml)
- 修正
HelloWorldFunctionIamRole的输出值(缺少n) - 建议添加环境变量配置,避免硬编码敏感信息
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > slack-bot-lambda Sample SAM Template for slack-bot-lambda Globals: Function: Timeout: 10 # 延长超时时间,确保Slack API调用完成 Environment: Variables: SLACK_SIGNING_SECRET: "" # 部署时填入或使用Secrets Manager SLACK_BOT_TOKEN: "" Resources: HelloWorldFunction: Type: AWS::Serverless::Function Properties: CodeUri: hello-world/ Handler: app.lambdaHandler Runtime: nodejs18.x Architectures: - x86_64 Events: HelloWorld: Type: Api Properties: Path: /hello/slack/events Method: post Outputs: HelloWorldApi: Description: "API Gateway endpoint URL for Prod stage for Hello World function" Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/slack/events/" # 修正路径为实际事件路径 HelloWorldFunction: Description: "Hello World Lambda Function ARN" Value: !GetAtt HelloWorldFunction.Arn HelloWorldFunctionIamRole: Description: "Implicit IAM Role created for Hello World function" Value: !GetAtt HelloWorldFunctionRole.Arn # 修正拼写错误
3. 额外注意事项
- 环境变量配置:不要在代码中硬编码
MY_SIGNING_SECRET和MY_TOKEN,通过Lambda控制台或SAM部署时注入环境变量,敏感信息建议使用AWS Secrets Manager存储。 - API Gateway路径:确保Slack事件订阅的URL与模板中定义的
/hello/slack/events一致,Outputs中的URL也需要同步修正。 - Lambda超时:默认3秒可能不足以完成Slack API调用,建议延长到10秒。
内容的提问来源于stack exchange,提问作者Tails
相关产品推荐
相关产品推荐

