Telegram Bot使用mysql2时TypeError属性读取错误的处理方法咨询
解决mysql2 + telegraf-mysql-session的TypeError问题(constructor读取失败)
一、问题根源定位
当getSessionKey返回undefined(比如ctx.from/ctx.chat不存在的场景),telegraf-mysql-session内部会生成无效的SQL查询,导致mysql2接收到undefined作为sql参数,触发Cannot read properties of undefined (reading 'constructor')错误。另外,AgentID/DealerID为null时参数处理不当,也会间接引发这类SQL构建异常。
二、分步解决方案
1. 修复getSessionKey返回值,避免undefined
修改telegraf-mysql-session的初始化配置,确保getSessionKey始终返回有效字符串或明确的null,杜绝undefined返回:
const session = new MySQLSession({ // 其他数据库配置... getSessionKey: (ctx) => { if (ctx.updateType === "callback_query") { ctx = ctx.update.callback_query.message; } // 兜底判断,避免返回undefined if (!ctx?.from || !ctx?.chat) { return null; } // 修正原代码的笔误:会话键应区分用户和聊天ID,避免同聊天内用户会话冲突 return `${ctx.from.id}:${ctx.chat.id}`; }, });
2. SQL查询前强制参数校验
所有涉及AgentID/DealerID的查询,先校验变量合法性,提前拦截无效请求:
async function queryAgentData(agentId) { // 校验参数是否为空 if (agentId === null || agentId === undefined) { console.warn("AgentID为空,跳过本次查询"); return null; } try { const [rows] = await connection.query('SELECT * FROM agents WHERE id = ?', [agentId]); return rows[0]; } catch (err) { console.error("Agent数据查询失败:", err); // 可选择抛出错误或返回默认值,根据业务需求调整 throw err; } }
3. 给mysql2连接添加全局错误捕获
防止单条查询错误导致整个Bot崩溃,给mysql2连接实例绑定错误监听:
const connection = mysql.createConnection({ // 你的数据库配置(host、user、password等) }); // 全局捕获连接级错误 connection.on('error', (err) => { console.error("MySQL连接异常:", err); // 致命错误触发自动重连 if (err.fatal) { reconnect(); } }); // 自定义重连逻辑 function reconnect() { console.log("尝试重新连接数据库..."); connection = mysql.createConnection(connection.config); connection.connect((err) => { if (err) { console.error("重连失败,10秒后重试:", err); setTimeout(reconnect, 10000); } else { console.log("数据库重连成功"); } }); }
4. 给会话中间件包裹错误处理
避免会话操作异常导致Bot冻结,在telegraf会话中间件外层添加捕获逻辑:
bot.use(async (ctx, next) => { try { await session.middleware()(ctx, next); } catch (err) { console.error("会话中间件错误:", err); // 给用户发送友好提示 await ctx.reply("服务暂时出现问题,请稍后再试"); // 继续执行后续中间件,防止Bot阻塞 await next(); } });
5. 清理无效会话数据(可选)
如果数据库中存在session_key为null/空字符串的无效记录,手动清理避免重复触发错误:
DELETE FROM sessions WHERE session_key IS NULL OR session_key = '';
三、验证方案
- 模拟AgentID/DealerID为null的场景,确认不再触发
constructor读取错误。 - 测试
ctx.from/ctx.chat不存在的场景(如频道消息),检查Bot是否能正常处理,不会冻结。
内容的提问来源于stack exchange,提问作者sb_thedev
相关产品推荐
相关产品推荐

