Telegraf session中间件报错:Cannot set properties of undefined
问题:Telegram Bot添加session中间件后ctx.session为undefined导致报错
添加session()中间件前Bot运行正常,但执行/start命令时触发以下错误:
Error in webhook handler: TypeError: Cannot set properties of undefined (setting 'state') at file:///C:/fm-telebot/index.js:134:21 at C:\fm-telebot\node_modules\telegraf\lib\composer.js:397:28 at C:\fm-telebot\node_modules\telegraf\lib\composer.js:165:111 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async execute (C:\fm-telebot\node_modules\telegraf\lib\composer.js:518:17) at async C:\fm-telebot\node_modules\telegraf\lib\composer.js:519:21 at async execute (C:\fm-telebot\node_modules\telegraf\lib\composer.js:518:17) at async C:\fm-telebot\node_modules\telegraf\lib\composer.js:519:21 at async C:\fm-telebot\node_modules\telegraf\lib\session.js:104:13 at async execute (C:\fm-telebot\node_modules\telegraf\lib\composer.js:518:17)
在/start命令中打印ctx.session显示为undefined,错误由expressApp.post()的捕获块捕获。尝试调整session中间件选项无效,需定位问题原因,或获取无需手动初始化会话的解决办法。
相关代码
Bot主代码
// Using import statements instead of require import express from "express"; import path, { dirname } from "path"; import { Telegraf, session } from "telegraf"; import { config } from "dotenv"; import { fileURLToPath } from "url"; import { PrismaClient } from "@prisma/client"; import { botSendMessage, sendServState, sendWPT } from "./helper_functions.js"; import ngrok from 'ngrok' config(); // Using Prisma ORM const prisma = new PrismaClient(); // Setup __dirname equivalent in ES module scope const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); // Initialize Express const expressApp = express(); const port = process.env.PORT || 3000; // Middleware to serve static files expressApp.use(express.static("static")); expressApp.use(express.json()); // Initialize the bot const bot = new Telegraf(process.env.BOT_TOKEN, { telegram: { webhookReply: false } }); bot.use(session()) // Start ngrok and set the webhook (async function() { try { // Connect ngrok to the specified port const url = await ngrok.connect(port); const WEBHOOK_URL = `${url}/telegram-webhook`; // Set the webhook for the bot await bot.telegram.setWebhook(WEBHOOK_URL); console.log(`Webhook set to ${WEBHOOK_URL}`); // Webhook handler for incoming Telegram updates expressApp.post('/telegram-webhook', (req, res) => { bot.handleUpdate(req.body) .then(() => { if (!res.headersSent) { res.sendStatus(200); } }) .catch((error) => { console.error('Error in webhook handler:', error); if (!res.headersSent) { res.sendStatus(500); } }); }); // Root endpoint to serve the main page expressApp.get("/", (req, res) => { res.sendFile(path.join(__dirname, "/index.html")); }); // Start the Express server expressApp.listen(port, () => { console.log(`Server running on port ${port}`); }); } catch (err) { console.error('Error setting up webhook or server:', err); } })(); bot.command("start", (ctx) => { console.log(ctx.from); console.log(ctx.session); ctx.session.state = 'idle' ctx.session.cur_command = null botSendMessage(bot, ctx, "Hello there! I am the FM helper bot.") });
botSendMessage函数
export function botSendMessage(bot, ctx, message){ bot.telegram.sendMessage(ctx.chat.id, `@${ctx.from.username}\n${message}`); }
解决方案
核心问题原因
手动调用bot.handleUpdate(req.body)时,没有让Telegraf的中间件链完整执行,session中间件的异步初始化逻辑未被正确触发,导致ctx.session未被创建。
修复步骤
替换手动Webhook处理为Telegraf内置方法
将原来的expressApp.post('/telegram-webhook', ...)路由替换为Telegraf提供的webhookCallback,它会自动处理请求上下文,确保中间件链(包括session)按顺序执行:// 替换原来的expressApp.post路由 expressApp.use(bot.webhookCallback('/telegram-webhook'));验证session中间件注册顺序
确保bot.use(session())在所有命令、监听函数之前注册,你的现有代码已经满足这一点,无需修改。优化消息发送函数(可选)
直接使用ctx.reply替代传入bot实例,代码更简洁且符合Telegraf最佳实践:export function botSendMessage(ctx, message){ ctx.reply(`@${ctx.from.username}\n${message}`); }调用时改为:
botSendMessage(ctx, "Hello there! I am the FM helper bot.")
修改后,ctx.session会被session中间件正确初始化,/start命令中的赋值操作不再报错。
内容的提问来源于stack exchange,提问作者Kaiwen Xie
相关产品推荐
相关产品推荐

