Telegram Bot报'No suggested keys error'的处理方法咨询
问题根因
No suggested keys error是Telegram隐私规则更新触发的已知异常:当用户主动删除与Bot的私聊会话、主动拉黑Bot时,Telegram服务端会直接作废该会话维度下所有已下发的自定义回复键盘缓存,如果Bot仍尝试向该失效会话发送携带ReplyKeyboardMarkup自定义键盘的消息,就会抛出该错误。
之前测试时功能正常,是因为测试阶段双方会话处于有效状态,键盘缓存未被服务端作废,用户删除会话后缓存失效才触发报错,和Bot本身的业务逻辑bug无关。
具体处理方案
- 全局异常兜底拦截
在所有消息发送、回复键盘编辑的逻辑外层增加异常捕获,匹配到No suggested keys error时,直接标记对应用户ID的会话为失效状态,清理本地存储的该用户关联的自定义键盘缓存、会话上下文数据,后续给该用户推送的首条消息不要携带自定义键盘,发送纯文本内容即可重建有效会话,避免异常中断Bot主进程。 - 基于ChatMemberHandler提前感知状态变更,从根源避免报错
ChatMemberHandler可以监听到私聊场景下用户与Bot的关系变更,在用户删除会话、拉黑Bot的第一时间清理本地缓存,就不会出现后续发消息触发报错的问题。以Python生态最常用的python-telegram-bot v20+版本为例,实现代码如下:
from telegram import Update from telegram.ext import ( ApplicationBuilder, ChatMemberHandler, ContextTypes ) async def handle_chat_member_change(update: Update, context: ContextTypes.DEFAULT_TYPE): # 过滤非私聊场景的事件 if update.effective_chat.type != "private": return new_user_status = update.chat_member.new_chat_member.status # 用户删除会话、拉黑Bot时,状态会更新为left或kicked if new_user_status in ("left", "kicked"): uid = update.effective_user.id # 清理本地存储的该用户所有自定义键盘缓存、会话状态数据 keyboard_cache = context.bot_data.get("private_chat_keyboard_cache", {}) if uid in keyboard_cache: del keyboard_cache[uid] if __name__ == "__main__": app = ApplicationBuilder().token("替换为你的Bot Token").build() # 注册处理器,注意要指定监听所有类型的聊天成员事件 app.add_handler( ChatMemberHandler(handle_chat_member_change, ChatMemberHandler.CHAT_MEMBER_TYPES.ALL) ) app.run_polling()
注意:使用该处理器前需要先到@BotFather开启对应Bot的聊天成员更新权限,操作路径:发送/mybots -> 选中目标Bot -> Bot Settings -> Group Privacy -> 开启
Receive chat member updates开关,私聊场景的状态变更也依赖该权限才能正常推送。
- 无侵入兼容方案
如果暂时不想调整事件监听逻辑,可以在所有调用消息发送、键盘编辑接口的参数中增加allow_sending_without_reply=True,同时对超过7天未产生交互的私聊用户,首条推送消息不要携带自定义键盘,先发送纯文本消息探测会话有效性,确认会话正常后再发送带交互键盘的内容,也能覆盖绝大多数该类异常场景。
内容的提问来源于stack exchange,提问作者bl4nk
相关产品推荐
相关产品推荐

