#OpenClaw #微信 #调试踩坑

记录一次通过微信发送文件附件(xlsx)时遭遇的连环报错,以及最终定位到 iLinkai API 大小写敏感问题的全过程。

本系列部署实录 · 配置续集 · 公网访问 · Headroom 接入 · 后续规划


背景

用 OpenClaw Agent 生成了一份评分标准表格(.xlsx),希望通过微信渠道直接投递给对话方,无需额外步骤。整个流程应该是:

  1. Agent 调用 message 工具,指定 media 参数(文件路径)

  2. openclaw-weixin 插件将文件上传到 iLinkai CDN

  3. CDN 地址写入微信文件消息,发送给对方

听起来很顺,实际踩了好几个坑。


一、连环报错

报错 1:sendMessage ret=-3 errmsg=invalid arguments

1
[tools] message failed: sendMessage ret=-3 errmsg=invalid arguments

原因:指定了错误的 accountId——两个机器人账号中,目标用户只与其中一个有聊天记录,用了另一个账号发送自然被拒。

报错 2:weixin not configured

1
[tools] message failed: weixin not configured: please run `openclaw channels login --channel openclaw-weixin`

原因:accountId 填写了 "default" 这个逻辑名称,插件实际使用运行时账号 ID,无法识别字符串 "default"

报错 3:cannot determine which account to use

1
2
weixin: cannot determine which account to use for to=<OPENID>
(2 accounts registered, none has an active session with this recipient)

原因:两个机器人账号都没有与该用户的活跃 session,插件无法自动判断用哪个账号发送。解决方法是让用户先从微信发一条消息过来,触发 session 建立。

报错 4:getUploadUrl returned no upload URL(持续失败)

1
[tools] message failed: uploadFileAttachmentToWeixin: getUploadUrl returned no upload URL

文字消息已经可以正常发出,但文件发送始终在这一步失败。看起来是接口问题——但为什么同样的配置文字能过、文件不行?


二、从日志中发现成功案例

翻 Docker 日志时,发现同一天早些时候有一次成功记录:

1
2
[weixin] sendWeixinMediaFile: file upload done filekey=<KEY> size=8208
sendFileMessageWeixin: success to=<OPENID>

成功发送的是另一个版本的同类文件。对比成功和失败时的请求参数,发现了关键差异:

场景 target 参数
✅ 成功(13:13) <OPENID_原始混合大小写>
❌ 失败(15:xx) <openid_全小写>

三、根本原因:getuploadurl API 大小写敏感

深入分析插件代码(@tencent-weixin/openclaw-weixin v2.4.6):

1
2
getUploadUrl → ilink/bot/getuploadurl
参数:to_user_id = <用户 openid>

to_user_id 使用全小写 openid 时,API 返回 {"ret":-1},没有错误说明,只有一个 -1

to_user_id 使用原始混合大小写 openid(即 getupdates API 返回的原始格式)时,正常返回 upload_param,上传成功。

而文字消息的 sendmessage 接口对大小写相对宽松,全小写也能发出去。所以才出现了「文字消息能发、文件发不了」的奇怪现象。

结论:ilink/bot/getuploadurlto_user_id 参数严格区分大小写。


四、修复方法

用正确大小写的 openid 重试,约 6 秒内上传完成,消息发送成功。

实际操作建议

  • 不要手动拼写 openid——从 incoming 消息上下文中取原始值,保持格式不变

  • 不要指定 accountId——让插件通过 context-token 自动解析(resolveOutboundAccountId),它会匹配有活跃 session 的账号

  • 文字消息对大小写宽松,文件上传严格,两者要区别对待


五、附:插件文件上传流程

openclaw-weixin 发文件的完整链路如下:

  1. 读取文件,计算 MD5 和 AES-128-ECB 加密后的大小

  2. 调用 ilink/bot/getuploadurl 获取 CDN 预签名参数

  3. 将文件内容加密后 PUT 到 CDN

  4. 调用 ilink/bot/sendmessage,附上 CDN 引用,发出文件消息

第 2 步是这次问题的发生点。对于图片类型(IMAGE)和普通文件(FILE)都走同一流程,都受大小写限制影响。


六、调试技巧

插件有独立日志文件,路径通常在 /tmp/openclaw/openclaw-<date>.log(容器重启后丢失)。日志为 JSON 格式,包含完整的 resp= 字段,能看到 API 原始返回,比 Docker 日志详细得多:

1
2
"uploadFileAttachmentToWeixin: getUploadUrl returned no upload URL
(need upload_full_url or upload_param), resp={\"ret\":-1}"

遇到文件投递问题,优先查这个日志。


延伸阅读