跳至主要內容
模組 4:精通 2 / 6
進階 Session 20 Error Handling Recovery

錯誤恢復

建構重試邏輯、錯誤分類和備用策略。

2026年3月20日 18 分鐘閱讀

你將學到什麼

錯誤在代理工作流中是不可避免的。API 回傳 429。建置失敗。測試中斷。檔案遺失。區分脆弱腳本與韌性代理的關鍵,在於它如何回應失敗 --- 而不是是否會遭遇失敗。

完成後,你將了解:

  • 如何將錯誤分類為可操作的類別
  • 搭配指數退避的重試模式
  • 當主要方法失敗時的備用策略
  • Claude Code 如何將錯誤轉化為資訊
  • 常見的失敗模式及其恢復策略

問題是什麼

一個天真的代理對所有錯誤一視同仁:它停下來。但並非所有錯誤都相同。

Error: ENOENT: no such file or directory     ← 路徑錯誤,可修復
Error: 429 Too Many Requests                 ← 暫時性的,等一下就好
Error: Cannot find module 'express'          ← 缺少依賴,安裝它
Error: SyntaxError: Unexpected token         ← 程式碼 bug,必須修復
Error: EPERM: operation not permitted         ← 需要使用者操作

每一種都需要完全不同的回應。對所有錯誤都停下來是浪費時間。對所有錯誤都重試則浪費更多。關鍵在於分類:在決定怎麼做之前,先理解你面對的是哪種錯誤。

如何運作

錯誤分類

每個錯誤都屬於三個類別之一:

┌─────────────────────────────────────────────────────┐
│              錯誤分類                                  │
│                                                      │
│  ┌──────────────────┐                                │
│  │   暫時性           │  → 搭配退避重試               │
│  │                   │                                │
│  │  • 速率限制        │  等一下就會成功。               │
│  │  • 網路錯誤        │  問題是暫時性的。               │
│  │  • 逾時           │                                │
│  │  • 伺服器 5xx     │                                │
│  └──────────────────┘                                │
│                                                      │
│  ┌──────────────────┐                                │
│  │   永久性           │  → 改變方法                   │
│  │                   │                                │
│  │  • 找不到檔案      │  重試不會有幫助。               │
│  │  • 語法錯誤        │  必須修復根本原因               │
│  │  • 型別不匹配      │  或嘗試不同的方法。             │
│  │  • 缺少模組        │                                │
│  └──────────────────┘                                │
│                                                      │
│  ┌──────────────────┐                                │
│  │  需要使用者操作     │  → 詢問使用者                  │
│  │                   │                                │
│  │  • 權限錯誤        │  代理無法自行解決               │
│  │  • 需要認證        │  這個問題。需要                  │
│  │  • 缺少設定        │  人工介入。                     │
│  │  • 需求模糊        │                                │
│  └──────────────────┘                                │
│                                                      │
└─────────────────────────────────────────────────────┘

重試模式

對於暫時性錯誤,標準方法是指數退避:

第 1 次嘗試:執行操作
            → 失敗(429 速率限制)
            → 等待 1 秒

第 2 次嘗試:再試一次
            → 失敗(429 速率限制)
            → 等待 2 秒

第 3 次嘗試:再試一次
            → 失敗(429 速率限制)
            → 等待 4 秒

第 4 次嘗試:再試一次
            → 成功!

每次嘗試的等待時間加倍。這可以防止不斷敲打被速率限制的 API,並給系統時間恢復。

┌────────────────────────────────────────────┐
│         指數退避                             │
│                                             │
│  嘗試次數  等待    累計耗時                   │
│  ───────  ────    ─────────                 │
│     1      0s          0s                   │
│     2      1s          1s                   │
│     3      2s          3s                   │
│     4      4s          7s                   │
│     5      8s         15s                   │
│     6     16s         31s  ← 通常在這裡停止  │
│                                             │
│  最大重試次數:大多數操作 3-5 次              │
│  最大等待時間:上限 30-60 秒                  │
│                                             │
└────────────────────────────────────────────┘

備用策略

當主要方法因永久性錯誤而失敗時,具韌性的代理會嘗試替代方案:

┌──────────────────────────────────────────────────┐
│           備用鏈                                   │
│                                                   │
│  主要方法:npm install express                     │
│     │                                             │
│     ▼ 失敗(找不到 npm)                           │
│                                                   │
│  備用 1:yarn add express                          │
│     │                                             │
│     ▼ 失敗(找不到 yarn)                           │
│                                                   │
│  備用 2:pnpm add express                          │
│     │                                             │
│     ▼ 成功                                        │
│                                                   │
│  繼續使用 pnpm 作為套件管理器                       │
│                                                   │
└──────────────────────────────────────────────────┘

備用機制在每個層級都適用:

檔案讀取備用:
  嘗試:讀取 src/config.ts
  備用:讀取 src/config.js
  備用:讀取 src/config.json
  備用:在 src/ 中搜尋 "config"

建置備用:
  嘗試:pnpm build
  備用:npm run build
  備用:yarn build
  備用:讀取 package.json 尋找建置腳本

測試備用:
  嘗試:pnpm test
  備用:npx jest
  備用:npx vitest
  備用:搜尋測試設定

Claude Code 如何處理工具錯誤

當 Claude Code 中的工具呼叫失敗時,錯誤訊息會以 tool_result 回傳 --- 就像成功結果一樣。AI 讀取錯誤並決定下一步該怎麼做。

┌───────────────────────────────────────────────┐
│        錯誤作為工具結果                          │
│                                                │
│  AI 呼叫:Bash("cat src/auth.ts")              │
│                                                │
│  工具回傳:                                     │
│  ┌────────────────────────────────────┐        │
│  │  tool_result:                      │        │
│  │  "cat: src/auth.ts: No such file   │        │
│  │   or directory"                    │        │
│  │  is_error: true                    │        │
│  └────────────────────────────────────┘        │
│                                                │
│  AI 讀取錯誤,推理:                             │
│  「這個檔案在那個路徑不存在。                     │
│   讓我搜尋 auth 相關的檔案。」                    │
│                                                │
│  AI 呼叫:Grep("auth", pattern="*.ts")         │
│                                                │
│  工具回傳:                                     │
│  ┌────────────────────────────────────┐        │
│  │  tool_result:                      │        │
│  │  "src/middleware/authenticate.ts"  │        │
│  │  "src/lib/auth-utils.ts"          │        │
│  └────────────────────────────────────┘        │
│                                                │
│  AI 適應:讀取正確的檔案                         │
│                                                │
└───────────────────────────────────────────────┘

這就是「錯誤即資訊」原則。錯誤不是停止信號 --- 它是幫助 AI 在下一步做出更好決策的資料。

錯誤恢復迴圈

將所有內容整合在一起,具韌性的代理遵循這個迴圈:

┌──────────────────────────────────────────┐
│          錯誤恢復迴圈                      │
│                                           │
│  1. 嘗試操作                              │
│          │                                │
│          ▼                                │
│  2. 是否成功?                            │
│     是 → 繼續下一步                        │
│     否 → 分類錯誤                          │
│          │                                │
│          ▼                                │
│  3. 錯誤類型?                            │
│     暫時性     → 重試(最多 3-5 次)       │
│     永久性     → 嘗試備用方法              │
│     需要使用者 → 報告並詢問                │
│          │                                │
│          ▼                                │
│  4. 恢復是否成功?                         │
│     是 → 繼續下一步                        │
│     否 → 升級處理                          │
│          │                                │
│          ▼                                │
│  5. 報告嘗試了什麼以及什麼失敗了           │
│                                           │
└──────────────────────────────────────────┘

關鍵洞見

好的錯誤恢復是區分脆弱腳本與韌性代理的關鍵。AI 應該將錯誤視為學習機會,而不是停止條件。

當錯誤發生時,它包含資訊:

  • 「找不到檔案」的錯誤告訴你路徑是錯的 --- 搜尋正確的路徑
  • 「找不到模組」的錯誤告訴你缺少依賴 --- 安裝它
  • 「型別錯誤」告訴你程式碼有 bug --- 讀取型別並修復不匹配
  • 「權限被拒」的錯誤告訴你操作需要更高權限 --- 詢問使用者

每個錯誤都縮小了解決方案的範圍。一個仔細讀取錯誤並適應的代理,能解決簡單腳本永遠無法解決的問題。

代理設計中最常見的錯誤是將所有錯誤都視為致命的。第二常見的錯誤是不加區分地重試所有東西。分類才是讓恢復有效的技能。

實作範例

建構具韌性的套件安裝流程

以下是你如何指示 Claude Code 以適當的錯誤恢復來處理真實世界場景:

Install the "sharp" image processing library in this project.
If it fails, diagnose the error and try alternative approaches.
Do not give up after the first failure.

具有良好錯誤恢復的代理行為:

步驟 1:嘗試 pnpm add sharp
  → 錯誤:node-gyp 建置失敗(缺少 libvips)

步驟 2:分類 → 永久性(缺少系統依賴)
  → 無法重試,必須改變方法

步驟 3:備用 → 檢查是否有預編譯二進位檔
  → 嘗試:pnpm add sharp --ignore-scripts
  → 然後:npx sharp-install

步驟 4:仍然失敗 → 嘗試替代函式庫
  → pnpm add jimp(純 JavaScript,無原生依賴)
  → 成功!

步驟 5:更新程式碼以使用 jimp 而非 sharp
  → 調整 import 和 API 呼叫
  → 執行測試以驗證

常見失敗模式與恢復

失敗分類恢復策略
ENOENT: file not found永久性搜尋檔案,檢查拼寫
429 Too Many Requests暫時性指數退避,最多重試 5 次
EACCES: permission denied需要使用者操作報告,建議 chmodsudo
Build failed: type error永久性讀取錯誤,修復型別不匹配
Test failed: assertion永久性讀取測試,修復邏輯或更新測試
Connection timeout暫時性以更長的逾時重試
Module not found永久性安裝缺少的依賴
Out of memory需要使用者操作建議增加記憶體或分批處理
Git conflict永久性讀取衝突標記,手動解決
Lint error永久性讀取規則,修復違規

設計錯誤感知的 CLAUDE.md 指令

你可以直接在專案指令中編碼恢復策略:

# Error Recovery Rules

When a build fails:
1. Read the FULL error output, not just the last line
2. If it's a type error, check the relevant type definitions
3. If it's a missing import, search for the correct path
4. If it's a dependency issue, run pnpm install first

When tests fail:
1. Run the failing test in isolation first
2. Read both the test and the implementation
3. Determine if the test or the code is wrong
4. Fix the root cause, not the symptom

Never retry more than 3 times for the same error.
If stuck after 3 attempts, report what you tried.

這為 Claude Code 提供了明確的恢復手冊,而不是依賴隱式推理。

前後對比

沒有錯誤恢復有錯誤恢復
代理在第一個錯誤時停下來代理分類並適應
所有錯誤一視同仁暫時性、永久性、需要使用者操作
沒有重試邏輯暫時性錯誤使用指數退避
沒有備用選項嘗試替代方法
錯誤就是失敗錯誤就是資訊
使用者必須不斷介入代理在可能的情況下自我修復

下一堂課

第 21 堂課涵蓋成本優化 --- 如何為每個任務選擇正確的模型、有效管理 token,以及設計平衡品質與成本的工作流。