錯誤處理:Error workflow / Retry / Wait
上線後的 workflow 半夜掛了,不會有人自動告訴你——除非你事先鋪好接住錯誤的網。這章教三件事:讓整條 workflow 掛的時候 Slack 通知你(Error workflow)、讓單一節點暫時失敗時自動重試(Retry on fail)、以及故意等一下避開 API 打太快被封鎖(Wait 節點)。做完,你的 workflow 才算「真的可以放著跑」。
為什麼上線前一定要接錯誤處理
第 10 章教你把 workflow 從 Manual 換成 Schedule,讓它每天早上 8:00 自動跑;第 16 章教你分流、合流、切批次。看起來 workflow 已經很聰明——直到某一天你發現:
- 週一早上 9 點:老闆問「上週的日報怎麼沒發?」你打開一看,Schedule 上禮拜三就悄悄失敗了,沒人知道。
- 發薪日:workflow 一次呼叫外部 API 100 次,被對方判 rate limit 擋掉一半,結果一半的人沒收到通知。
- 某個星期六凌晨:對方系統打嗝 30 秒,你的 workflow 剛好那時候跑,一次失敗——但其實只要重試一次就會成功。
這三種情境,n8n 都有現成的解法:Error workflow 接第一種、Retry 接第三種、Wait 接第二種。它們不是三選一,是 Production workflow 該同時有的三層保險——通知你錯了、單點自救、避免打死對方。這章一次講完,之後你的 workflow 才算「上線 grade」。
三種錯誤處理各管什麼
先把三張牌攤開——名字很像,管的層級完全不同:
| 機制 | 接住什麼層級的錯 | 做什麼 | 什麼時候用 |
|---|---|---|---|
| Error workflow | 整條 workflow 掛(任何節點死到底) | 觸發另一條專門處理錯誤的 workflow(例:Slack 通知你) | 每一條 production workflow 都該綁 |
| Retry on fail(節點層) | 單一節點失敗(例:某個 HTTP Request 掛) | 該節點自動重試 N 次,中間隔一段時間 | API 偶爾抽風、網路 blip、輕微 rate limit |
| Wait 節點 | 不是接錯——是預防錯 | workflow 停在這裡等 X 秒/等到某個時間/等外部 callback | 避免打太快被 rate limit、要間隔通知、等對方系統處理完 |
三者關係:Wait 是事前預防、Retry 是事中自救、Error workflow 是事後補救。一條上線的 workflow 三個都該有,缺一個就少一層防線。
Error workflow 是什麼——一條專門接錯誤的 workflow
Error workflow 是另外一條獨立的 workflow——不是設定,是一整條 workflow。它跟你平常的 workflow 一樣,只是它的第一個節點必須是 Error Trigger。
運作邏輯是這樣的:
-
你先做一條 Error workflow
用 Error Trigger 當第一個節點,後面接 Slack / Email / Discord / 資料庫,做「發生錯誤時要通知誰/記到哪」。
-
其他 workflow 各自「指定」用這一條當 Error workflow
每條 production workflow 在 Settings 裡選 Error Workflow = 剛剛那條。
-
某條 workflow 出錯 → n8n 自動觸發 Error workflow
Error Trigger 節點會收到出錯 workflow 的名字、時間、錯誤訊息、掛在哪一個節點等資料,交給下游節點處理。
Error Trigger 節點會把錯誤資訊塞到 $json,常用欄位:
| 欄位 | 意思 | Expression 寫法 |
|---|---|---|
| 出錯的 workflow 名字 | 是哪條 workflow 掛了 | {{ $json.workflow.name }} |
| 出錯的 workflow ID | 方便點連結進去看 | {{ $json.workflow.id }} |
| 錯誤訊息 | n8n 給的錯誤描述 | {{ $json.execution.error.message }} |
| 掛在哪一個節點 | 是哪個節點死的 | {{ $json.execution.lastNodeExecuted }} |
| Execution URL | 直接點進去看該次執行紀錄 | {{ $json.execution.url }} |
動手做:建一條全公司共用的 Error workflow
目標:做一條 Error Handler workflow,出錯時自動貼一則訊息到 Slack 的 #alerts 頻道。設一次,之後所有 workflow 都用它。
-
建新 workflow,命名
Error Handler左側 Workflows → + Add workflow。畫布空白後,先按 Ctrl+S 存檔,名字打
Error Handler——名字取有辨識度的,之後在 Settings 下拉才找得到。 -
加 Error Trigger 節點
Canvas 空白處按 Tab(或左上 + 號)叫出節點抽屜 → 搜尋
Error Trigger→ 選它。它會落到 canvas 上,作為這條 workflow 的起點。Error Trigger 沒有任何參數要設,放上去就好。 -
加 Slack 節點接在後面
Error Trigger 右邊拖出線,落點放開叫節點抽屜 → 搜尋
Slack→ 選 Send a message action。第 7 章如果還沒設過 Slack credential 就先設一個(OAuth 授權 Slack workspace)。 -
Slack 節點參數:Channel 填
#alertsChannel 欄可以用 By Name 選現有頻道,或直接打
#alerts。這個頻道要先在 Slack 建好,並且把 n8n bot 邀請進去(Slack 頻道 → Integrations → Add App)。 -
Slack 訊息內容(用 Expression 塞錯誤資料)
Text 欄切到 Expression 模式(點欄位右上的 fx),貼上:
⚠️ Workflow 錯誤通知 Workflow: {{ $json.workflow.name }} 掛在節點: {{ $json.execution.lastNodeExecuted }} 錯誤訊息: {{ $json.execution.error.message }} 時間: {{ $json.execution.startedAt }} 點這裡看: {{ $json.execution.url }}底下的 preview 會顯示假資料樣本,看起來對就 OK。
-
Save,然後把右上 Active toggle 拉成綠色
按 Ctrl+S → Active toggle ON。Error workflow 沒 Active 是不會被觸發的——這是第一名踩雷。
-
做完了——這條之後全公司共用
Error Handler workflow 設完就放著,不用天天管。它只在別條 workflow 出錯時被叫起來執行一次,沒事的時候完全不佔資源。
每條 workflow 綁定 Error workflow
Error Handler 建好之後,還要逐一去每一條 production workflow 指定它——不指定的話出錯還是沒人管。
-
打開你要監控的 workflow
從 Workflows 清單點進去,畫布會展開。
-
右上角三點選單 → Settings(或按 Ctrl+,)
會彈出 Workflow Settings 面板,裡面有 Timezone、Save Failed Executions、Error Workflow 等選項。
-
Error Workflow 下拉選
Error Handler下拉會列出你這個 instance 上所有包含 Error Trigger 節點的 workflow。找到
Error Handler點下去。 -
Save Settings
面板右下 Save。之後這條 workflow 出錯就會自動觸發 Error Handler。
-
把所有 production workflow 都設一遍
不會自動套用——每條 workflow 都要各自指定。可以列個清單一次做完,之後新增的 workflow 也記得順手設。
節點層 Retry on fail:讓單一節點自己重試
Retry on fail 是設在單一節點上的自動重試機制——這個節點失敗時,n8n 會等一下再打一次、再等一下再打一次,重試次數用完才判定失敗。適合對付「短暫性錯誤」(transient error):API 暫時 503、網路抖一下、對方系統重啟中。
怎麼設
-
打開你想重試的節點面板
例:HTTP Request 節點、Slack 節點、Google Sheets 節點——任何節點都能設。
-
切到 Settings tab
節點面板頂端有 Parameters / Settings 兩個 tab,點 Settings。
-
Retry On Fail 切成 ON
會展開兩個新欄位:Max Tries 與 Wait Between Tries。
-
Max Tries 填重試次數(含首次執行)
常用值
3—5。填3代表最多打三次(第 1 次失敗、等一下、第 2 次失敗、等一下、第 3 次失敗才判死)。 -
Wait Between Tries 填毫秒數
常用值
1000(1 秒)到5000(5 秒)。太短沒等對方系統喘息、太長 workflow 拖很久。API rate limit 錯誤建議5000以上。
什麼場景適合開 Retry
| 場景 | 適不適合 Retry | 為什麼 |
|---|---|---|
| API 回 503 Service Unavailable | 非常適合 | 對方服務暫時掛掉,過幾秒通常會恢復 |
| API 回 429 Too Many Requests(rate limit) | 適合(配合 Wait Between Tries 拉長) | 等一下就解鎖 |
| Network timeout/連線失敗 | 適合 | 網路 blip 通常瞬間就過 |
| API 回 401 Unauthorized(credential 過期) | 不適合 | 再打 100 次也一樣過期,浪費時間;該去重新授權 credential |
| API 回 404 Not Found(資料真的不存在) | 不適合 | 資料就是沒有,重試也生不出來 |
| 你的 Expression 寫錯(undefined 之類) | 不適合 | 邏輯錯誤不會因為重試就變對 |
Wait 節點:故意停一段時間
Wait 節點做一件很簡單的事——讓 workflow 停在這裡,時間到了才往下走。用來降速、對齊時間、或等外部系統回話。
Wait 有三種模式
| Resume 模式 | 什麼時候繼續 | 典型場景 |
|---|---|---|
| After Time Interval | 等 X 秒/分/小時/天 | 每一批間隔 1 秒避免打太快、發通知後等 10 分鐘再檢查狀態 |
| At Specified Time | 等到某個特定日期時間(例:2026-08-20 09:00) | 「明天早上 9:00 再繼續」「下個月 1 號才發帳單」 |
| On Webhook Call | 等外部系統打 webhook 回來才繼續 | 發送簽核連結 → 等對方點了才繼續;發起金流 → 等對方 callback 才確認 |
最常用的 pattern:Wait 配 Split In Batches 避免 rate limit
假設你要對 500 筆資料呼叫外部 API,一次全打會被 rate limit 擋。改成:Split In Batches(batch size = 10)→ HTTP Request → Wait 1 second → 回到 Split In Batches 下一批。這樣每秒 10 個 request,通常都在對方 rate limit 允許範圍內。第 16 章有完整例子。
Executions 紀錄與 debug
錯誤處理接住了、通知發出去了——接下來你要做的事是打開 Executions 頁面看到底是哪個節點、什麼原因掛的。Executions 頁是你 debug workflow 的主戰場。
Executions 頁在哪
- 全域:左側主導覽 Executions,看整個 instance 所有 workflow 的執行紀錄。
- 單一 workflow:進入某條 workflow → 頂端 Executions tab,只看這條的。
怎麼讀紀錄
| 顏色/圖示 | 意思 |
|---|---|
| 綠色 Success | 所有節點都跑完,沒錯 |
| 紅色 Error | 中途有節點掛了,workflow 沒跑完 |
| 橘/黃色 Running | 正在跑(例:Wait 節點在等) |
| 灰色 Waiting | Waiting for webhook 或 At Specified Time 等外部條件 |
點任一筆紅色 Execution 進去 → 會看到 canvas 樣的視覺化:失敗的節點會被紅框 highlight,點該節點就看到當時的 input / output / error 訊息。這是找 bug 最快的方式。
Pin data:測試時很好用的省 API 次數招
開發時每改一個節點就重跑一次 workflow,會不斷打真的 API(Gmail、Slack、Sheets),既慢又浪費 quota。Pin data 可以讓你把某個節點的一次成功 output 釘住,之後 workflow 重跑到那個節點時,會直接吃 pin 住的資料,不會真的打 API。
用法:跑一次成功 → 點該節點的 output → 上面有個「圖釘」icon → 按下去,output 就固定了。改完下游要看效果,重跑 workflow,pinned 節點會直接吐 pinned 資料。開發完取消 pin 再上線。
EXECUTIONS_DATA_MAX_AGE 環境變數,預設 336 小時 = 14 天)。想留久一點請找 IT 調;或者你在 Error Handler 裡順手把錯誤寫到 Google Sheets / DB,就永久留底了。常見錯誤情境對照
把最常遇到的錯誤跟建議做法列個對照,你之後看到某個錯誤訊息可以直接查怎麼救:
| 錯誤情境 | 該用什麼 | 做法 |
|---|---|---|
| 429 Too Many Requests(打太快) | Wait + Retry | Wait 節點降速;該節點 Retry on fail 開,Wait Between Tries 拉到 5000ms 以上 |
| 503 Service Unavailable / 短暫網路錯 | Retry | Max Tries = 3~5,Wait Between Tries = 2000ms |
| 401 Unauthorized(credential 過期) | Error workflow(通知你手動處理) | Retry 沒用;靠 Error workflow 通知 → 你去 Credentials 頁面重新授權 |
| Network timeout | Retry + Wait | Retry on fail + Wait 5s,避免立刻再打一次時對方還沒恢復 |
資料格式錯(Expression undefined) |
前面加 Set 或 IF 節點驗證 | Retry 沒用(邏輯錯),要在資料進來時就用 Set 給預設值、或 IF 過濾 |
| Sub-workflow not found | Error workflow 通知 | Sub-workflow 被刪或 ID 改了;通知你去修 Execute Workflow 節點的引用 |
| Webhook Trigger 沒收到 | Error workflow 抓不到(不算錯)+ 主動 Schedule 檢查 | Webhook 沒被打不會觸發任何錯誤;加一條 Schedule workflow 每小時檢查「上小時應該有幾筆」 |
| Gmail Trigger poll 太慢 | 不是錯,是設計問題 | 把 Poll Times 改成 Every Minute;真要即時就找有 push webhook 的服務 |
錯誤處理常見卡關
設完錯誤處理,你可能會遇到「明明設了但沒動」的狀況。這幾種對照一下八成能自己救:
| 症狀 | 可能原因 | 怎麼救 |
|---|---|---|
| workflow 掛了但 Error workflow 沒觸發 | (1) 該 workflow 的 Settings 沒指定 Error Workflow (2) Error Handler 這條 workflow 沒 Active |
回到出錯 workflow → Settings → Error Workflow 下拉選 Error Handler;再去 Error Handler workflow 確認右上 Active 是綠的 |
| Retry 5 次還是全部失敗 | 錯誤根本不是暫時性的(credential 過期、資料本來就不對、邏輯錯) | Retry 只延遲失敗、不會解決根本問題。看 Executions 的錯誤訊息,是 401/400/404/JS error 就別靠 Retry,去修根本原因 |
| Wait 節點 workflow 一直停不動 | (1) On Webhook Call 模式但對方沒打 URL 回來、(2) 超過 65 秒 Wait 用 SQLite 遇到重啟遺失了、(3) At Specified Time 時區設錯(跟 workflow Settings 的 Timezone 差 8 小時) | 檢查給對方的 webhook URL 是否正確、對方端有沒有真的觸發 callback;長 Wait 換 Postgres 外部 DB;At Specified Time 對照 Settings → Timezone |
| Executions 頁看不到剛剛跑的紀錄 | (1) 頁面沒 refresh、(2) workflow 剛 Active 但 Schedule 還沒到、(3) Executions 保留天數已過 | 按瀏覽器 F5;確認 Schedule 下次時間到了沒;管理員看 EXECUTIONS_DATA_MAX_AGE 是不是被調短 |
| Error workflow Slack 訊息內容都是 undefined | Expression 打錯欄位路徑 | Error Trigger 節點跑一次(用一條真的會錯的 workflow 觸發),看 output 面板實際 $json 長什麼樣,照著抄欄位 |
| Error workflow 自己也掛了(Slack 節點失敗) | Error Handler 沒有再上一層錯誤處理(本來就不會遞迴) | Error Handler 保持簡單、少依賴(避免用容易掛的 API);重要用途可以在 Error Handler 內加第二種通知(例:Slack 失敗就寄 Email backup) |
| 開了 Retry 之後發現重複寄了 3 封信 | 該節點是非冪等操作,重試 = 重複執行副作用 | 寄信/建單這類節點關掉 Retry,改在前面加一個「先查有沒有」的節點;或該節點失敗就整條 workflow 失敗,走 Error workflow 通知你手動處理 |
| Error Workflow 下拉是空的,找不到 Error Handler | 你的 Error Handler workflow 裡沒有 Error Trigger 節點 | 回去 Error Handler,確認第一個節點是 Error Trigger(不是 Manual、不是 Webhook)。n8n 只把「含 Error Trigger 節點」的 workflow 列在下拉裡 |
常見問題
一定要有 Error workflow 嗎?
Retry 會不會導致重複執行、產生副作用(例:寄兩封信、扣兩次款)?
Wait 節點消耗資源嗎?可以 Wait 一整天嗎?
多條 workflow 能共用同一個 Error workflow 嗎?
{{ $json.workflow.name }} 就能顯示是哪條掛的。唯一例外:如果某類 workflow 的錯誤要通知不同的人(例:計費 workflow 通知財務、營運 workflow 通知客服),可以做兩三條 Error workflow 分別綁不同對象。Error workflow 自己掛了會怎樣?
「Continue On Fail」是什麼?跟 Retry 有什麼不一樣?
Stop Workflow(預設,會掛)、Continue(節點掛但吐空資料繼續走)、Continue (using error output)(節點多長一條 error 分支,錯誤資料走那條)。Continue On Fail 適合「這個節點失敗沒關係,可以繼續」的場景——例:批次處理 100 個客戶,其中 3 個失敗,剩下 97 個還是要處理完。跟 Retry 可以並用:先 Retry 3 次還是失敗,再走 Continue 繼續下一批。