Boloop 阅读示意图(AI 生成):上传结果不明时,先核对记录,再决定是否重试。

上传按钮一直转,最后报了超时,第一反应通常是再点一次。但这个动作隐含了一个未经确认的判断:刚才的文件一定没有上传成功。

Boloop 在 2026 年 10 月 16 日遇到过一次结果不明的上传操作。管理员身份已经在真实浏览器中确认,一份 Skill 草稿也已保存;随后,云端浏览器的文件选择与上传操作工具超时,后续只读检查没有恢复可见状态。

当时能确定的是工具没有返回可用结果。附件究竟有没有写入,仍然未知。我们没有继续盲目上传,也没有把这次超时直接归因于网站组件。

先确定超时发生在哪一层

一次文件上传至少经过几个边界:操作工具选择文件,浏览器发出请求,服务器接收并校验,存储完成写入,客户端读取响应,再把附件关联到资源。

其中任何一层停止等待,用户都可能看到“超时”。但上游停止等待,不表示下游一定停止工作。即使文件已经到达存储,响应没有被浏览器读到,界面也可能仍然不知道结果。

因此,排查时先记录最后一个已知事实:文件是否被选中、请求是否发出、是否收到响应、附件列表是否出现记录、草稿是否已经关联。缺哪一段,就把哪一段保留为未知。

那次 Boloop 事故中,支持的浏览器连接恢复方式未能恢复检查,所以附件结果没有得到确认。这个限制决定了下一步应等待可读回状态,而不是换一个说法宣布上传失败。

保留现场,比清空表单更有用

上传遇到问题时,至少有两份工作值得保留:已经填写的内容,以及原来选择的文件。错误提示如果只剩下一句“失败,请刷新”,就把恢复成本都交给了用户。

我们在检查源码时,发现当时的上传组件没有 XHR 超时设置,解析错误和同步初始化异常也可能让界面停留在忙碌状态。随后准备的健壮性候选增加了 90 秒等待上限、较清楚的错误与不确定提示,以及文件和草稿保留。

这个等待上限是候选实现的产品选择,不能解释为“上传到 90 秒一定失败”。超时之后应该说停止等待,并指导用户核对结果,不能保证服务器没有写入。

候选还处理了组件卸载、旧回调和初始化异常,防止一个已经失去上下文的响应继续改变当前界面。这些工作改善了可见的失败恢复,但没有因此查明浏览器操作工具为什么超时。

结果不明时,先做只读核对

恢复正常访问后,我会先看原草稿和附件库。核对时使用文件名称、大小、资源归属和版本等实际信息;如果存在同名文件,进一步对照文件字节或校验值,不能只凭显示名判断。

接下来的动作取决于读回结果:

| 读回结果 | 适合的下一步 | |---|---| | 附件存在,草稿已正确关联 | 继续检查内容,不再重复上传 | | 附件存在,尚未关联 | 核实它就是目标文件,再完成关联 | | 能确认附件未写入 | 保留原文件,按正常入口重试 | | 仍无法确认结果 | 保留未知状态,先恢复观察能力 |

这张表描述的是恢复方法,不是声称那次未知操作后来已经逐项完成。2026 年 10 月 16 日的记录没有确认上传结果,也没有确认该轮候选已经部署。

手动重试,也需要服务端守住一致性

把重试按钮留给用户,不能替代服务端约束。用户可能连点,也可能在另一个标签页重复操作;网络重连以后,旧请求还可能返回。

Boloop 早期的后端回归处理过同一资源与版本的重复绑定,要求原子地拒绝冲突,同时保留软件不同平台、架构这类合法变体。附件仍被有效引用时,归档也要被阻止。

这些约束解决的是数据一致性。客户端保留文件和输入,解决的是恢复体验。两者配合,才不会出现界面看似恢复,数据却已经重复或引用错乱的情况。

同样,上传成功也不等于内容已经公开。附件关联、草稿保存和显式发布仍是不同动作。恢复上传时,不应顺便替用户执行发布。

怎么验证恢复,而不是只验证报错

早在另一轮隔离验收中,我们注入过对象存储故障。表单显示安全错误,恢复存储后,使用同一表单与原文件手动重试,附件成功出现,未保存内容也仍在。

这证明了那条受控故障路径可以恢复。它没有证明 10 月 16 日的操作工具超时已被解决;一个发生在应用存储层,一个发生在浏览器操作链上,证据不能互换。

对真实上传问题,完整验证还应继续到正常管理员入口、上传、保存关联、发布,以及公开下载后的字节核对。只有走过这些步骤,才能对对应范围作结论。

如果你正在实现一个上传界面,可以先检查三个小问题:等待是否有结束条件,失败后原文件与输入是否还在,结果不明时能否查到权威记录。它们比一个反复出现的“重试”按钮更能决定恢复是否顺利。

而作为操作者,看到超时时最值得停下来的地方,是下一次写入之前。先查结果,再决定是否重试,往往能少制造一个新的问题。