Discord.js机器人闲置30分钟后触发DiscordAPIError[10062]崩溃
解决Discord.js机器人闲置后触发DiscordAPIError[10062]的问题
问题描述
我的Discord.js机器人所有命令、交互功能初始运行均正常,但将其在线闲置30分钟后,再次执行命令时会触发如下DiscordAPIError[10062]错误并崩溃:
/home/yetnt/bots/mJb/node_modules/@discordjs/rest/dist/index.js:640 throw new DiscordAPIError(data, "code" in data ? data.code : data.error, status, method, url, requestData); ^ DiscordAPIError[10062]: Unknown interaction at handleErrors (/home/yetnt/bots/mJb/node_modules/@discordjs/rest/dist/index.js:640:13) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async BurstHandler.runRequest (/home/yetnt/bots/mJb/node_modules/@discordjs/rest/dist/index.js:736:23) at async REST.request (/home/yetnt/bots/mJb/node_modules/@discordjs/rest/dist/index.js:1387:22) at async ChatInputCommandInteraction.deferReply (/home/yetnt/bots/mJb/node_modules/discord.js/src/structures/interfaces/InteractionResponses.js:69:5) { requestBody: { files: undefined, json: { type: 5, data: { flags: undefined } } }, rawError: { message: 'Unknown interaction', code: 10062 }, code: 10062, status: 404, method: 'POST', url: 'https://discord.com/api/v10/interactions/1107289296546832485/aW50ZXJhY3Rpb246MTEwNzI4OTI5NjU0NjgzMjQ4NTpNcmhrYWh0ZGdndzQ5SjJWT3BEYWNhWDNsMHIwT2YwaWxlVFMyclByd2ZuNWpLejNPSmEyOG14T3kwOXNZc3l5VnFHTkgwVUhKYW55Q0RmajlXb1NoSDgzUnNYN1pKZEFzNU9LR3puaFZKVm1XbjZJRHZydkVZTEpNcnRSUHBIdA/callback' } Node.js v18.16.0 [nodemon] app crashed - waiting for file changes before starting...
重启机器人后功能恢复正常,但再次闲置后问题复现。
核心原因
- Discord交互令牌的有效期仅为15分钟,机器人闲置后首次执行命令时,数据库查询(如
User/Inventory/Cooldown模型查询)因连接休眠、无索引等原因耗时过长,导致超过令牌有效期才调用interaction.deferReply(),Discord已不再识别该交互。 - 未针对
10062错误做捕获处理,导致错误直接崩溃机器人进程。
解决方案
1. 优先响应交互,再处理耗时逻辑
Discord要求必须在3秒内对交互做出响应(包括延迟回复),需将deferReply放在所有耗时操作最前端,避免超时:
// 修改rob.js的callback函数 callback: async (client, interaction) => { // 先立即执行延迟回复,确保在3秒内响应Discord const deferSuccess = await interaction.deferReply().catch(err => { console.error("延迟回复失败:", err); return false; }); if (!deferSuccess) return; try { // 所有数据库查询和业务逻辑放在这里 let victimId = interaction.options.get("victim").value const sf = rndInt(1, 2) // 2 = success; 1 = failure let victim = await User.findOne({userId: victimId}) // ... 剩余原有业务逻辑 } catch (error) { // 判断交互状态后再发送错误提示 if (interaction.deferred) { await interaction.editReply('操作出错了').catch(() => {}); } // ... 原有错误日志逻辑 } }
2. 优化数据库连接,防止闲置断开
如果使用MongoDB/Mongoose,添加连接保活配置,避免闲置时连接被断开:
// 数据库连接代码中添加以下配置 mongoose.connect(process.env.MONGO_URI, { keepAlive: true, keepAliveInitialDelay: 300000, // 5分钟保活心跳 connectTimeoutMS: 10000, socketTimeoutMS: 45000 });
3. 捕获10062错误,避免机器人崩溃
在命令处理的全局catch块和命令内部catch块中,专门捕获该错误:
// 修改handleCommands.js的catch块 catch (error) { if (error.code === 10062) { console.log("交互已过期:用户在令牌失效后执行命令"); return; } console.log(`执行命令时出错:`); console.log(error) } // 修改rob.js的catch块 catch (error) { if (error.code === 10062) { console.log(`命令${interaction.commandName}的交互已过期,用户ID:${interaction.user.id}`); return; } // ... 原有错误回复和日志逻辑 }
4. 添加数据库索引,加快查询速度
给User/Inventory/Cooldown模型的userId字段添加索引,大幅减少查询耗时:
// User模型示例 const UserSchema = new mongoose.Schema({ userId: { type: String, index: true }, // 添加索引 balance: Number, // ... 其他字段 }); // Inventory和Cooldown模型同理添加userId索引
验证效果
修改完成后,让机器人闲置超过30分钟再执行命令,将不会触发Unknown interaction错误,且机器人不会崩溃。提前执行的deferReply会刷新交互令牌有效期,后续编辑回复操作可正常进行。
内容的提问来源于stack exchange,提问作者YetNT
相关产品推荐
相关产品推荐

