You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS Lambda部署Python Telegram Bot触发KeyError:'body'报错排查

问题场景

使用Python(telebot库)、AWS Lambda与API Gateway开发Telegram Bot过程中,调试Lambda函数时出现无法定位根因的运行错误。

原始Lambda代码
import telebot
import datetime

TOKEN = 'xxx'

def lambda_handler(event, context):
   bot = telebot.TeleBot(TOKEN)
   # Extract the message key over payload's body
   message = json.loads(event['body'])
   print(message)
   
   # Split between three variables bellow
   chat_id = message['chat']['id'] # Chat ID will guide your chatbot reply 
   sender = message['from']['first_name'] # Sender's first name, registered by user's telegram app
   text = message['text'] # The message content
   
   if text.lower().strip() == "/time":
   
       current_time = datetime.strftime(datetime.now(), "%H:%M:%S")
       bot.send_message(chat_id, "Right now its {} UTC.".format(current_time))
       
   else:
       pass 
运行报错信息
{
  "errorMessage": "'body'",
  "errorType": "KeyError",
  "stackTrace": [
    "  File \"/var/task/lambda_function.py\", line 10, in lambda_handler\n    message = json.loads(event['body'])\n"
  ]
}
测试用事件JSON
{
    "update_id": 0000000,
    "message": {
        "message_id": 000000,
        "from": {
            "id": 00000000,
            "is_bot": false,
            "first_name": "myname",
            "last_name": "mysurname",
            "username": "sursurname",
            "language_code": "it"
        },
        "chat": {
            "id": 000000,
            "first_name": "myname",
            "last_name": "mysurname",
            "username": "sursurname",
            "type": "private"
        },
        "date": 1654697178,
        "forward_from": {
            "id": 00000000,
            "is_bot": false,
            "first_name": "mysurname",
            "last_name": "mysurname",
            "username": "sursurname",
            "language_code": "it"
        },
        "forward_date": 0000000000,
        "text": "ciao"
    }
}
根因分析
  • 触发KeyError: 'body'的直接原因:当前使用的测试事件是Telegram原生推送的更新结构,本身不存在body字段。event['body']是API Gateway开启Lambda代理集成时才会封装的字段,原始Telegram请求内容会被序列化为字符串放在这个字段下,直接用原生Telegram事件做Lambda入参测试时,自然找不到这个键。
  • 代码存在3个隐藏bug,就算解决body字段问题也会运行失败:
    • 调用了json.loads()但没有导入json标准库,会触发NameError
    • 更新内容层级读取错误:json.loads(event['body'])拿到的是完整的Telegram更新对象,消息实体存放在update['message']下,直接读取message['chat']['id']会再次触发KeyError
    • datetime方法调用错误:import datetime导入的是模块,strftime和now()是datetime.datetime类的方法,原写法会触发AttributeError
  • 原代码没有返回API Gateway要求的标准响应格式,线上运行时会被API Gateway判定为执行失败,返回502错误。
修复方案
  1. 补全缺失的依赖导入,增加场景兼容逻辑,同时支持本地原生Telegram事件测试、线上API Gateway转发请求两种场景
  2. 修正消息层级读取逻辑、datetime方法调用逻辑
  3. 补充标准Lambda返回值,适配API Gateway要求

修复后的可运行代码:

import telebot
import datetime
import json

TOKEN = 'xxx'

def lambda_handler(event, context):
    bot = telebot.TeleBot(TOKEN)
    # 自动适配两种入参场景
    if 'body' in event:
        # 线上API Gateway转发场景,解析body里的原始更新内容
        update = json.loads(event['body'])
    else:
        # 本地测试场景,直接传入的是Telegram原生更新对象
        update = event
    print(update)
    
    # 正确读取消息层级
    message = update['message']
    chat_id = message['chat']['id']
    sender = message['from']['first_name']
    text = message['text']
    
    if text.lower().strip() == "/time":
        current_time = datetime.datetime.strftime(datetime.datetime.now(), "%H:%M:%S")
        bot.send_message(chat_id, f"Right now its {current_time} UTC.")
    
    # 返回API Gateway要求的标准响应
    return {
        'statusCode': 200,
        'body': 'success'
    }
额外排查注意点
  • 线上部署时必须开启API Gateway的Lambda代理集成,否则请求内容不会被封装到event['body']字段中
  • 如果要模拟API Gateway的请求格式做本地测试,需要把完整的Telegram更新内容序列化为字符串,放在事件的body字段下,示例格式如下:
{
  "body": "{\"update_id\": 123456, \"message\": {\"message_id\": 1, \"from\": {...}, \"chat\": {...}, \"date\": 1654697178, \"text\": \"/time\"}}"
}

内容的提问来源于stack exchange,提问作者Difettoso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 05:09:25