我自己的一个工作流——决定新WhatsApp联系人是交给机器人还是交给我的那道门——从周四到周日失败了24次。整整71小时。我是周一早上发现的,当时因为一个无关的原因打开了执行列表。
这对一个靠卖自动化服务吃饭的人来说,挺丢人的。所以我没有只修好那一个工作流就完事,而是去测量了主生产实例上全部225个工作流的错误处理真实状态。以下是实例中保留的所有执行记录——因为开启了清理策略,这是8月18日至24日共六天的窗口数据。
核心数据:0.21%的失败率不算什么,85%才是问题
环境是n8n 2.35.5,队列模式,Postgres存储。0.21%的失败率完全可以接受。但85%这个数字不能接受——那是失败时没有通知任何人的比例。
n8n的错误处理是选择加入(opt-in)机制,按工作流单独配置。你需要先建一个触发器为Error Trigger节点的工作流,然后在其他每个工作流里打开Settings → Error Workflow,指向那个处理器。没有任何一个开关能把它一键应用到所有已建好的工作流,或者未来新建的工作流。
这就是一个每周都在增长的清单上的逐项勾选。没有人是故意忘记的。你只是在晚上11点建好了第61个工作流,它跑通了,你激活它,然后继续下一件事。选择加入式安全网的失效模式就是:覆盖率在悄悄衰减,而你脑子里的数字还停留在"嗯,我们有错误处理"。
我的覆盖率已经衰减到了43%。
按工作流分组查看失败数据,重点看最后一列
我把失败按工作流分组,并加了一列:该工作流是否挂了错误处理器。
别看失败次数,看最后一列。所有超过9小时的窗口都属于没有防护的工作流。最长的是70.9小时——一个WhatsApp机器人网关,三天内失败了24次,而我当时在忙别的事。没有火烧眉毛,没有客户投诉。机器人只是不回复新联系人,而我发现它的唯一原因是我主动去查了。
有防护的工作流也失败了——总共16次。但它们最长的故障窗口只有1.2小时,因为有东西通知了我。
这就是Error Trigger的全部价值主张,不是"减少失败",而是让失败以小时计而不是以天计。
最讽刺的发现:错误处理器本身没有防护
我的实例上有三个包含Error Trigger节点的工作流,它们是处理器——负责发送Telegram警报。下面是每个处理器覆盖了多少个活跃工作流:
每个处理器都是无防护的。而覆盖15个工作流的那个处理器,就是上面表格里同一行:它在六天窗口内自己就失败了13次。
这13次失败意味着,15个工作流完全没有告警,也没有任何途径发现问题。错误处理器无法报告自己的错误,因为报告错误的东西就是错误处理器本身。用YAML写出来就是:谁来守护守护者?
你也不能通过把处理器A指向处理器B来解决这个问题。那只是把沉默点往后移一跳,还加了一个你迟早会忘记的循环。捕获器必须从n8n外部被监控。
我的解决方案:一个处理器,而不是每个项目一个
扇入(fan-in)优于扇出(fan-out)。一个统一的Error Trigger工作流,格式化输出{{ $json.workflow.name }}和{{ $json.execution.id }},把告警集中到一个入口。然后从外部监控这个处理器本身——用独立的心跳检查或定时任务确认它还活着。
这次审计的教训很直接:选择加入的安全网,默认就是会烂掉的。如果你跑自动化,花十分钟检查一下你的错误处理覆盖率。别等到周一早上才发现,你的机器人已经沉默了三天。
热门跟贴