[Bug] aiocqhttp:引用机器人自己发送的图片无法解析(get_msg 返回空 url + 裸文件名)
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 22/100
Hướng nghiên cứu
Start in astrbot/core/astr_main_agent.py around lines 1601-1621 and 1665, where has_embedded_image is set and the quoted-image fallback is skipped, then read _materialize_media_ref in astrbot/core/utils/media_utils.py. A reasonable done state is that a reply image which fails to materialize falls through to image_resolver.py instead of injecting the [Image unavailable] text, with a test covering that path. The SnowLuma protocol-side resolution is a separate, open question.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
问题描述
AstrBot 4.29.3(Docker)+ aiocqhttp(OneBot v11)+ SnowLuma。
机器人通过插件发送一张图片(Comp.Image),QQ 端显示正常。随后用户引用这条机器人自己发出的图片消息并补上文字,AstrBot 无法解析引用中的图片:
- 日志出现两条 WARN;
- 请求中注入
TextPart("[Image unavailable]"); - 模型据此回复“图片没加载出来”。
与 #10179(私聊中引用图片无法解析)的触发场景不同:这里是引用机器人自己发送的图片,并且协议端对这张图的 get_msg / get_image 都只返回空 url 和裸文件名。相关 PR #10225 / #10194 曾尝试修复 quoted image 的引用解析,但均未合并;当前 master(2026-11-03)仍存在下文的短路逻辑。
如何复现?
- 让机器人发送任意一张图片(插件使用
Comp.Image即可),确认 QQ 端正常显示; - 在 QQ 中引用该图片消息,并回复任意文字;
- 查看 AstrBot 日志。
预期行为
引用中的图片能作为视觉输入送给模型。如果协议端确实无法提供可访问的图片来源,至少不应让模型产生“我这边图片加载失败”的表述。
实际行为
图片被判定为 unresolved media ref,模型收到 [Image unavailable],并回复图片未加载。
AstrBot 版本
4.29.3
操作系统
Linux(Docker)
部署方式
Docker
使用的消息平台适配器
aiocqhttp(OneBot v11)+ SnowLuma
错误日志
[WARN] Image processing in reply chain failed for unresolved media ref
name='<md5>.png' len=36: [Errno 2] image reference is not an existing local file
or a valid payload: '<md5>.png'
[WARN] Quoted image is unavailable (FileNotFoundError): unresolved media ref
name='<md5>.png' len=36
每条引用该图片的消息都会稳定出现这两条 WARN。
根因分析
-
发送侧:
astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py:36-44将Image/Record段无条件转为base64://后发送给协议端。协议端把图片缓存为 md5 命名的文件。 -
协议端返回:用户引用该消息后,
get_msg返回的图片段为:{"type":"image","data":{"url":"","file":"<md5>.png","sub_type":0,"summary":"[图片]"}}没有
file_id、没有本地路径、没有 CDN URL。对同一张图单独调用get_image/get_file,同样只得到url: ""。 -
解析失败:适配器构造出
Image(file="<md5>.png", url="")。astrbot/core/utils/media_utils.py的_materialize_media_ref()(约 463 行)只接受http(s)://、file:、data:、base64://、裸 base64,或真实存在的本地文件;裸文件名在这里抛出FileNotFoundError(错误文案约 646 行),describe_media_ref()(约 326、382 行)将其格式化为unresolved media ref name='<md5>.png' len=36。astrbot/core/pipeline/preprocess_stage/stage.py:215先记录第一条 WARN,随后astrbot/core/astr_main_agent.py:1610再次失败并记录第二条 WARN。 -
fallback 被短路:
astrbot/core/astr_main_agent.py:1601-1621只要 reply chain 中存在Image就把has_embedded_image置为True;convert_to_file_path()失败后注入[Image unavailable]。由于has_embedded_image已为True,约 1665 行的if not has_embedded_image:分支被跳过,现成的astrbot/core/utils/quoted_message/image_resolver.py(会依次尝试get_image/get_file/get_group_file_url/get_private_file_url)根本没有机会执行。 -
即使进入该 fallback,SnowLuma 对同一张图的
get_image/get_file仍只返回url: "",因此该协议端场景还需要额外的解析途径;但第 4 点会让支持get_image的协议端也一起失效,属于独立的 AstrBot 侧缺陷。
代码位置
- 发送:
astrbot/core/platform/sources/aiocqhttp/aiocqhttp_message_event.py:36-44 - 媒体解析:
astrbot/core/utils/media_utils.py:463(_materialize_media_ref)、:326/:382(describe_media_ref)、:646(FileNotFoundError文案) - 引用图片处理与 fallback 短路:
astrbot/core/astr_main_agent.py:1601-1621、:1665 - 预处理阶段日志:
astrbot/core/pipeline/preprocess_stage/stage.py:215 - 已存在但未触发的引用解析器:
astrbot/core/utils/quoted_message/image_resolver.py
修复建议
- 最小修复:
astr_main_agent.py中把has_embedded_image改为“图片成功物化后才置为True”,或在物化失败时仍进入 quoted fallback。这样get_image可用的协议端能恢复正常。 - SnowLuma 场景:
get_msg和get_image都只给空url+ 裸文件名。若可通过协议端共享缓存目录、get_private_file_url或额外参数解析,请在ImageResolver中补上;若确实无法解析,warning 建议带上reply message_id与协议端 action 的原始返回,便于区分协议端限制和 AstrBot 缺陷。 - 失败提示:解析失败时不要注入
[Image unavailable](或改成中性文本,例如“引用中的图片无法获取”),也可以只记录日志并通过事件暴露给插件,避免模型对用户输出“图片加载失败”。 - 发送侧:考虑到 #6717 中维护者说明 base64 是为兼容“协议端与 AstrBot 不同机部署”而保留,这里不建议直接改回
file://。如果协议端能访问callback_api_base,可以在发送后登记图片的可回取 URL / 协议端file_id映射,供引用解析使用;否则优先级应低于第 1、3 点。
相关 issue / PR
- #10179(open):私聊中引用图片无法解析,触发场景与本条不同,且未提供日志/根因;
- #3895(closed):v4.7.4 下“引用机器人自身消息 + 图片无法识别”,当时以“插件生成的图片不计入上下文”关闭,本路径未修复;
- #10225、#10194(closed,未合并):曾尝试解析 quoted image 的 opaque / unusable reference;当前 master 仍存在第 4 点的短路问题。
辅助信息
日志与文件名已脱敏:不含 QQ 号、服务器 IP、Cookie、token 或人格名。
检查清单
- Ngôn ngữ chính
- Python
- Star
- 46.4k
- Fork
- 3.4k
- Merge trung bình
- 1 ngày 10 giờ
- Pull request đã merge (30 ngày)
- 123
Chuẩn bị môi trường
- Có Dockerfile hoặc tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của AstrBotDevs/AstrBot
-
enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
AstrBotDevs/AstrBot#11038 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
AstrBotDevs/AstrBot#11034 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
AstrBotDevs/AstrBot#10999 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Bug] OpenAI-compatible Gemini 工具 schema const 导致 400Có thể đã có người làm @arccat-114 đã nhận 16 ngày trước. Đang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 77/100
AstrBotDevs/AstrBot#10720 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Bug] Discord slash command sync aborts with KeyError when a plugin handler is defined in a submoduleCó thể đã có người làm @yuexia5 đã nhận 21 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 77/100
AstrBotDevs/AstrBot#10626 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của AstrBotDevs/AstrBot
Issue tương tự
-
`destroy` sans terminal répond « Aborted. » au lieu de réclamer `--yes` comme `clean` et `reset`Đang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
stephrobert/dsoxlab#354 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
hardware help wanted testing
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 77/100
jasonacox/pypowerwall#472 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Bug]: DoubleMLRDDData accepts a score_col that is no data column (as in its docstring example); the running variable then becomes a covariate and RDFlex failsCó thể đã có người làm @vrjdev đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
DoubleML/doubleml-for-py#455 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Bug]: Python mod.Box[T] annotation gets a false generic_arg edge that replaces the parameter_type one ('is' on tree-sitter nodes)Có thể đã có người làm @rohit-jsfreaky đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
Graphify-Labs/graphify#5110 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày