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

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未被创建。

修复步骤

  1. 替换手动Webhook处理为Telegraf内置方法
    将原来的expressApp.post('/telegram-webhook', ...)路由替换为Telegraf提供的webhookCallback,它会自动处理请求上下文,确保中间件链(包括session)按顺序执行:

    // 替换原来的expressApp.post路由
    expressApp.use(bot.webhookCallback('/telegram-webhook'));
    
  2. 验证session中间件注册顺序
    确保bot.use(session())在所有命令、监听函数之前注册,你的现有代码已经满足这一点,无需修改。

  3. 优化消息发送函数(可选)
    直接使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:04:56