
在使用 pycord 构建 slash 命令时,`ctx.respond()` 返回的是 `interaction` 对象而非 `message` 对象;若直接访问 `.id` 会误取交互 id(interaction id),导致后续 `fetch_message()` 因 id 无效而抛出 `404 not found (10008)` 错误。正确做法是通过 `.message.id` 获取实际发送消息的 id。
Discord 的 Slash 命令响应机制与传统消息发送不同:调用 ctx.respond() 后,Discord 首先创建一个 交互(Interaction),然后异步生成并返回一条响应消息。该响应被封装在 Interaction.message 属性中,而 Interaction 本身拥有独立的 .id(即 Interaction ID),它不能用于 fetch_message()——因为 fetch_message() 只接受真实消息的 ID。
✅ 正确写法:从 Interaction.message.id 提取消息 ID
将原代码中的:
msg = await ctx.respond(embed=embed, ephemeral=True) msg_id = msg.id # ❌ 错误:这是 Interaction ID
改为:
msg = await ctx.respond(embed=embed, ephemeral=True) await msg # 确保响应已提交(可选,但推荐) msg_id = msg.message.id # ✅ 正确:获取实际 Message 对象的 ID
? 注意:msg.message 在 ephemeral=True 下仍有效(只要未过期),但需确保 ctx.respond() 已完成。PyCord v2.6+ 中,await ctx.respond(...) 默认返回 Interaction,其 .message 属性会在响应就绪后自动填充(通常毫秒级)。为保险起见,可显式 await msg 或添加短延迟(如 await asyncio.sleep(0.5)),但非必须。
✅ 完整修正版代码
import asyncio
import discord
from discord.ext import commands
from discord.commands import slash_command
class Test(commands.Cog):
def __init__(self, bot):
self.bot = bot
@slash_command(name='test', description='演示如何正确编辑 Slash 响应消息')
async def test(self, ctx):
embed = discord.Embed(
description="The message I want to get by id"
)
# 发送初始响应
interaction = await ctx.respond(embed=embed, ephemeral=True)
# ✅ 关键修正:从 interaction.message 获取真实消息 ID
try:
msg_id = interaction.message.id
except AttributeError:
# 兜底:若 message 尚未就绪(极罕见),等待并重试
await asyncio.sleep(0.3)
if not interaction.message:
await ctx.followup.send("⚠️ 消息未及时生成,请重试", ephemeral=True)
return
msg_id = interaction.message.id
# 模拟延迟后编辑
await asyncio.sleep(2)
# 获取当前频道(注意:ephemeral 消息仅存在于 Interaction 所在频道,且不可跨频道 fetch)
channel = self.bot.get_channel(ctx.channel_id)
if not channel:
await ctx.followup.send("❌ 无法获取频道,请检查权限", ephemeral=True)
return
try:
# ✅ 使用正确的 msg_id 获取消息
message = await channel.fetch_message(msg_id)
new_embed = discord.Embed(
description="✅ 编辑成功:new message test"
)
await message.edit(embed=new_embed)
except discord.NotFound:
await ctx.followup.send("❌ 消息未找到:可能已被删除或 ID 无效", ephemeral=True)
except discord.Forbidden:
await ctx.followup.send("❌ 机器人无编辑权限,请检查角色权限", ephemeral=True)
except Exception as e:
await ctx.followup.send(f"❌ 编辑失败:{type(e).__name__}", ephemeral=True)
def setup(bot):
bot.add_cog(Test(bot))⚠️ 重要注意事项
- Ephemeral 消息限制:ephemeral=True 的消息只能由发送者和机器人查看,且 fetch_message() 在私有频道(如 DM)或某些受限频道中可能失败。确保机器人拥有 Read Message History 权限。
- ID 时效性:消息 ID 一旦生成即永久有效(除非消息被删除),但 interaction.message 在交互超时(默认 15 分钟)后可能变为 None。
- 不要混淆对象类型:ctx.respond() → Interaction;ctx.send() / channel.send() → Message;fetch_message() 输入必须是 Message.id。
- 调试技巧:打印 type(msg) 和 msg.id 可快速验证是否误用了 Interaction ID。
掌握这一关键区别,即可稳定实现 Slash 命令响应的延时编辑、状态更新等高级交互逻辑。










