本文整理自 2026 年 9 月 20 日的 OnBalls 本地研究。2026 年 10 月 15 日仅做网站文字与链接适配,没有复测,也没有把历史样本更新为当前全库。
一个流程显示失败,并不能单凭这条提示知道它做到了哪里。它可能还没开始写数据,也可能已经写完,只是最后的确认没有回来。
这两种情况都可能让操作者想按“重试”,但需要的处理不同。把整个流程重跑一遍,有时会补上缺失步骤,有时会把已经完成的动作再做一次。
设计自动化时,可以先回答一个问题:如果它今天停在中间,另一个人能否看着记录接手?
先分清三种状态
拿“把一批收藏写入数据库”作例子。为了讨论恢复,我们把记录分为三种状态:确定未提交、确定已提交、是否提交仍未知。这是本文的简化示意,实际系统可能需要更细的状态。
确定未提交时,可以按流程规则重试。确定已提交时,先核对结果,避免重复写入。状态未知时,第一步是查目标系统有没有这项结果;找不到足够证据,就应当让人判断下一步。
最值得演练的时刻,是“提交成功,但成功确认尚未记录”。正常演示很容易绕过它,真实故障却可能把人留在这个不确定区间。
2026 年 9 月 20 日这轮研究用 200 条真实收藏搭了一个本地 SQLite 写入原型。同一批记录重复运行后仍为 200 条;在提交前、提交后确认前分别注入 Python 异常,关闭并重新连接数据库后重试,也按预先定义的规则处理。这是本地异常注入,没有测试真实断电或商业平台的外部发送接口。(依据:2026 年 9 月 20 日本地研究记录;实验范围见文末说明。)
给操作一个能够认回来的编号
稳定编号的作用,是让系统能够辨认“这是不是同一项操作”。例如每条收藏有固定 ID,写入端就可以围绕这个 ID 设计重复处理规则。
规则还需要回答:同一个 ID 的内容变了怎么办?可以选择拒绝并报告、更新现有记录,或者保留版本。无论选择哪一种,都应该提前写清。否则“去重成功”可能只是掩盖了一次内容冲突。
人们常把这一类重复执行保护称为幂等(idempotency)。具体保障到哪里,要看实现、存储和外部接口。数据库里的去重约束,不能自动覆盖另一个服务上的发信、付款或建单动作。
错误分支负责通知,恢复还要有判断
n8n 官方说明可以配置错误工作流,在执行失败后触发,也提供主动抛错的节点。这些能力帮助流程表达“出了什么问题”;它们本身并不证明每个动作重复执行都是安全的。官方错误处理说明
因此,一条有用的错误通知应当告诉接手人:哪个任务、停在哪一步、哪些结果已经确认、哪些状态仍未知、下一步查哪里。只有一句“任务失败,请重试”,仍把关键判断留给了现场猜测。
可以给每个流程放一张失败接管卡:
| 要留的信息 | 一个可用的写法 |
|---|---|
| 操作编号 | 批次编号加记录 ID,重试时沿用同一规则 |
| 最后确认状态 | 已读取;写入是否完成仍待核查 |
| 结果核对入口 | 目标表、查询方式或可追溯的结果记录 |
| 重试条件 | 确认未提交,或重复保护在此动作上已验证 |
| 转交条件 | 状态无法确认、内容冲突或超出重试次数 |
| 接手后记录 | 查到了什么、做了什么、最终结果是什么 |
用低风险演练检查接管卡
先选只操作本地副本的小流程。正常跑一次,重复运行一次,再分别在提交前和提交后、确认前中断。每次都检查记录数量、内容以及执行状态,而不是只看界面有没有变绿。
如果你还不能从记录中回答“哪项需要重试”,先补日志与核对入口。如果系统能避免同一条记录重复写入,也要继续测试内容冲突,确认它没有静默吞掉更新。
对需要调用外部服务的正式流程,还应逐项验证那个接口的行为与授权边界。本地演练提供的是一种检查方法,不能替外部系统作保证。
一个值得交付的自动化,应当把失败后的下一步也交代清楚。你可以从自己的接管卡开始:今天停在任意一步,明天还有人能知道发生了什么。
研究范围与使用说明
实验只覆盖 200 条真实收藏的本地 SQLite 写入、重复运行及 Python 异常注入;没有真实断电、生产平台发信、付款或外部建单测试。原始收藏与内部实验附件不随网页提供。 外部文档只用于支持当时的概念说明;产品界面、功能和政策发生变化时,应回到官方页面核对。