Telebot通过用户ID发私信失败,请求排查400错误问题
Telegram机器人广播消息报错(Bad Request: chat not found)解决方案
问题概述
原本可通过数据库存储的用户ID向所有VIP用户发送广播消息,现在调用Telegram API时出现400错误:
A request to the Telegram API was unsuccessful. Error code: 400. Description: Bad Request: chat not found
已确认数据库能成功获取用户ID,格式示例:'1**30**095,5**30**076,9**0**079'
代码错误分析
- 循环参数错误:发送消息的循环中,
chat_id=users传入的是整个用户ID列表,而Telegram API要求传入单个聊天ID,这是核心报错原因。 - 用户ID类型不匹配:数据库存储的用户ID可能是字符串类型,但Telegram API要求
chat_id必须是整数,类型不匹配会导致API识别失败。 - 无效用户ID未处理:部分用户可能已拉黑机器人或注销账号,直接发送会触发报错并中断整个广播流程。
- 冗余事务提交:查询操作无需执行
conn.commit(),属于无效代码。
解决方案
- 修正循环中的
chat_id参数,使用当前循环的单个用户ID(user_id)而非整个列表(users) - 将数据库取出的用户ID转换为整数类型
- 为单个消息发送增加异常捕获,跳过无效用户,保证广播继续执行
- 移除查询后的
conn.commit()语句,添加数据库连接关闭操作防止泄漏
修正后的完整代码
def send_cast(message): try: msg1 = message.text.split(None, 1)[1] except IndexError: bot.send_message(message.chat.id, text="请输入要广播的内容!", parse_mode="Markdown") return user = message.chat.id conn = connect_to_db() cursor = conn.cursor() try: db_users = "select user_id from UFM_USERS where type ='VIP'" cursor.execute(db_users) u = cursor.fetchall() # 将用户ID转换为整数类型 users = [int(row[0]) for row in u] except (Exception, psycopg2.DatabaseError) as e: bot.send_message(message.chat.id, text=f"数据库查询错误:{str(e)}", parse_mode="Markdown") conn.close() return finally: conn.close() # 确保数据库连接关闭 # 验证管理员权限 if user not in m.admin: bot.send_message(message.chat.id, text="你需要管理员权限才能执行此操作‼️", parse_mode="Markdown") return # 发送广播消息 success_count = 0 fail_count = 0 for user_id in users: try: bot.send_message(chat_id=user_id, text=msg1, parse_mode="Markdown") success_count += 1 except Exception as e: fail_count += 1 # 记录失败日志方便后续排查 print(f"向用户 {user_id} 发送消息失败:{str(e)}") # 反馈广播结果 bot.send_message( message.chat.id, text=f"广播完成:成功发送 {success_count} 条,失败 {fail_count} 条", parse_mode="Markdown" )
额外优化说明
- 增加了广播内容的输入校验,避免用户未输入内容时触发报错
- 统计广播成功/失败数量,便于管理员掌握执行结果
- 打印失败日志,方便定位无效用户ID问题
内容的提问来源于stack exchange,提问作者PRIST LEGACY
相关产品推荐
相关产品推荐

