Codex无法粘贴图片(arboard分片等待时间过小导致超时)问题修复(INCR分片:Incremental Transfer(增量传输)无法粘贴彩色图片Failed to paste image
2026/9/3 5:25:13 网站建设 项目流程

https://github.com/shangxiang0907/codex-wsl-clipboard-bridge

https://github.com/shangxiang0907/codex-wsl-clipboard-bridge/commit/fabfb4af94ef1e3cb3e8901e49344785742a8536

文章目录

  • 一张彩色截图为什么让 Codex 误报“剪贴板没有图片”
    • 现象
    • 先把链路拆开
    • 几次合理但错误的猜测
      • 会不会是会话上下文太长
      • 会不会是 Wayland 和 X11 后端选错
      • 会不会是颜色太丰富,PNG 压缩算法有问题
    • 抓住 X11 selection 的所有权变化
    • 真正的根因:分片之间只等 10 毫秒
    • 修复:绕开 INCR,而不是牺牲图片
    • 验证
    • 对系统其他服务的影响
    • 排障方法上的收获

一张彩色截图为什么让 Codex 误报“剪贴板没有图片”

从 WSLg、X11 selection、xclip到 Codexarboard的 10 毫秒超时

现象

在 WSLg 中运行 Codex CLI 时,同样使用Ctrl+V

  • 一些界面截图可以正常粘贴;
  • 一张2520×1490的游戏指南页面截图却反复失败;
  • Codex 报错称剪贴板为空,或没有它请求的图片格式:
Failed to paste image: no image on clipboard: The clipboard contents were not available in the requested format or the clipboard is empty.

这条错误很容易让人怀疑图片分辨率、颜色数量、PNG 大小,甚至会话上下文长度。
实际根因都不在这些地方。

先把链路拆开

这个环境中的完整数据流是:

Windows 截图 → WSLg Wayland image/bmp → ImageMagick PNG32 → X11 CLIPBOARD image/png → Codex CLI / arboard

服务日志已经确认 BMP 读取、PNG 转换和 X11 发布成功:

bridged 2520x1490 image (11264454 byte BMP) to X11 as PNG

在发生故障的同一个终端中,xclip也能完整读出图片:

xclip-selectionclipboard-tTARGETS-o|tr'\0''\n'xclip-selectionclipboard-timage/png-o>/tmp/clipboard-test.pngfile/tmp/clipboard-test.pngstat-c'%s bytes'/tmp/clipboard-test.png

结果是有效的2520×1490RGBA PNG,大小约 1.37 MB。这排除了格式缺失、
文件损坏和超大输入限制。

几次合理但错误的猜测

会不会是会话上下文太长

不会。错误发生在图片进入对话之前,是本地剪贴板读取失败。conversation recap
和模型上下文还没有机会处理这张图片。

会不会是 Wayland 和 X11 后端选错

强制删除WAYLAND_DISPLAY并让 Codex 使用DISPLAY=:0后仍然失败。
这说明后端选择不是这次问题的充分解释。

会不会是颜色太丰富,PNG 压缩算法有问题

同尺寸合成图测试确实显示,内容熵会显著改变 PNG 大小:

内容BMPPNG32
纯色11.26 MB17.9 KB
渐变11.26 MB18.8 KB
照片式纹理11.26 MB7.58 MB
随机颜色11.26 MB12.92 MB

但实际失败截图只有约 1.37 MB,而且 ImageMagick、fileidentify
xclip都能正常处理。颜色丰富度只是增加故障概率的相关因素,不是根因。

我们一度实现了自适应 PNG8 量化,实测没有解决问题,随后完整撤销。这一点很
重要:没有端到端证据时,不应以损失画质来掩盖传输层缺陷。

抓住 X11 selection 的所有权变化

X11 剪贴板不是一块永久保存数据的共享内存。当前 selection owner 必须在消费方
请求格式时现场提供数据。

通过 XFixes 监听复现过程,得到如下事件:

19:30:00 event=changed TIMESTAMP,TARGETS,UTF8_STRING,TEXT 19:30:02 event=changed TARGETS,image/png xclip -selection clipboard -t image/png -i candidate.png

第二个事件之后没有其他程序覆盖 selection。Codex 失败时,PNG owner 仍然存在,
并且image/png仍在TARGETS中。

问题因此被压缩到最后一段:Codex 如何从 X11 owner 读取 PNG。

真正的根因:分片之间只等 10 毫秒

Codex CLI 0.152.0 包含arboard 3.6.1。检查该版本的
src/platform/linux/x11.rs
可以看到:

constLONG_TIMEOUT_DUR:Duration=Duration::from_millis(4000);constSHORT_TIMEOUT_DUR:Duration=Duration::from_millis(10);

读取开始时,arboard最多等待 4 秒。如果 selection owner 使用 X11INCR
协议分片发送大属性,每收到一个有效分片后,下一分片的等待时间却被重置为仅
10 毫秒:

*timeout_end=Instant::now()+SHORT_TIMEOUT_DUR;

WSLg、X server 或低优先级xclip只要有一次调度间隔超过 10 毫秒,
arboard就返回ContentNotAvailable。Codex 将它格式化成“no image on
clipboard”,掩盖了真实的分片超时。

这也解释了为什么故障看似与颜色和大小有关:PNG 越大,INCR 分片越多,撞上一次
10 毫秒调度空隙的概率越高。但它不是稳定的字节阈值,同一张图也可能偶发成功。

在 X11 协议(X Window System)的上下文中,INCR 是 Incremental Transfer(增量传输)机制的缩写。
它是 X11 剪贴板(Selection)协议中用于处理大数据量传输的一种握手协议。

修复:绕开 INCR,而不是牺牲图片

从消费者侧看,理想修复是让arboard使用合理的分片超时,例如每个有效分片后
重新等待 1~4 秒。不过桥接器不能修改用户当前安装的 Codex。

本项目采用生产者侧兼容修复:用一个小型 Python/ctypesX11 PNG selection
owner 替代xclip

新 owner:

  1. 只操作当前用户的 X11CLIPBOARD
  2. 只声明TARGETSimage/pngTIMESTAMP
  3. 调用XExtendedMaxRequestSize启用 X11 BIG-REQUESTS;
  4. 在安全上限内用一次XChangeProperty返回完整 PNG;
  5. 不使用 INCR,因此不会触发arboard的 10 毫秒分片超时;
  6. selection 被其他程序接管时收到SelectionClear并退出;
  7. 服务停止时由 systemd control group 一并清理。

本机 X server 报告的最大请求大小约为 16.7 MB。实现额外预留了请求头和 Xlib
封装空间;超过安全上限时明确失败,不会截断或静默损坏图片。

验证

先用一张约 7.58 MB 的高复杂度 PNG 做逐字节往返测试:

direct owner round-trip: 7578809 bytes

随后执行仓库验证:

XFixes event delivery: OK Static and runtime verification: OK

最后重新截取同一个2520×1490Dungeon Lootr Beginner Guide 页面,Codex
立即成功粘贴并能正确识别页面导航、状态卡、地下城主图和页面目录。

对系统其他服务的影响

新 owner 的权限和作用范围与原来的xclipowner 基本一致:

  • 不监听网络;
  • 不创建系统级服务;
  • 不操作 X11PRIMARYSECONDARYselection;
  • 不读取图片以外的剪贴板内容;
  • 新的复制操作会自然取代它并使其退出;
  • PNG 只在用户私有运行目录和 owner 进程内存中短暂存在。

它改变的是图片数据的 X11 传输方式,而不是桌面的剪贴板语义。

排障方法上的收获

这次问题最值得保留的不是某一条 ImageMagick 参数,而是分层验证的方法:

源格式是否存在 → 转换结果是否有效 → selection owner 是否仍存在 → TARGETS 是否包含消费方请求的 MIME → 直接读取是否成功 → 消费方具体依赖如何处理协议

“没有图片”只是上层错误文案,不代表剪贴板真的为空。只有把 Wayland、X11 selection、MIME 转换、INCR/BIG-REQUESTS 和消费库逐层拆开,才能找到真正需要修改的那一行。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询