用 AI 除錯與讀懂錯誤訊息:從貼上堆疊追蹤到定位根因的完整流程

用 AI 除錯與讀懂錯誤訊息:從貼上堆疊追蹤到定位根因的完整流程

錯誤訊息不是天書,而是最直接的線索。本文教你如何把堆疊追蹤、log 與程式碼一起餵給 ChatGPT 或 Claude,用系統化提問定位根因,並避免盲目套用 AI 給的修法。含實際範例、提問模板與常見陷阱。

為什麼要用 AI 來除錯

除錯是每位工程師花最多時間的工作之一。傳統流程是把錯誤訊息丟到 Google 或 Stack Overflow,翻找相似案例再自己拼湊答案。AI 助手如 ChatGPT、Claude 改變了這件事:你可以把錯誤訊息、相關程式碼與執行環境一次交給它,讓它同時扮演搜尋引擎、資深同事與橡皮鴨的角色。

但很多人用 AI 除錯的方式是錯的,只丟一行「這段程式壞了幫我修」,得到的往往是猜測式的答案。真正有效的做法,是把 AI 當成協助你「讀懂線索」的夥伴,而不是許願機。本文會拆解一套可重複的流程。

第一步:先讀懂錯誤訊息的結構

在把任何東西貼給 AI 之前,你自己要先看懂錯誤訊息的三個部分:例外類型(exception type)、訊息內容(message)、堆疊追蹤(stack trace)。以 Python 為例:

Traceback (most recent call last):
  File "app.py", line 42, in process_order
    total = sum(item['price'] for item in cart)
  File "app.py", line 42, in <genexpr>
    total = sum(item['price'] for item in cart)
KeyError: 'price'

這裡例外類型是 KeyError,訊息是 'price',堆疊追蹤告訴你出錯的檔案與行號(app.py 第 42 行)。光看這三點,就知道某個 item 字典裡沒有 price 這個鍵。堆疊追蹤要從最下面往上讀,最底部是實際拋出例外的位置,往上則是呼叫鏈。

第二步:給 AI 足夠的上下文

AI 除錯的品質,取決於你給的資訊量。一個好的除錯提問,至少要包含以下四項:

  1. 完整的錯誤訊息與堆疊追蹤(不要只貼最後一行)。
  2. 出錯的那段程式碼,以及相關的呼叫端。
  3. 你的執行環境(語言版本、框架版本、作業系統)。
  4. 你「預期」發生什麼,實際「又」發生了什麼。

以下是一個可直接套用的提問模板:

我在執行下面這段程式時出現錯誤,請幫我定位根本原因並說明為什麼。

【環境】Python 3.12,FastAPI 0.110
【預期】購物車加總所有商品價格回傳 total
【實際】拋出 KeyError: 'price'

【完整錯誤】
(把 traceback 全部貼上)

【相關程式碼】
(把 process_order 與呼叫它的地方貼上)

請先說明根因,再給修正建議,並指出這個問題可能還藏在哪些地方。

注意最後一句「還藏在哪些地方」,這會讓 AI 不只修眼前這一行,而是幫你找出同類問題。

第三步:用追問縮小範圍

AI 第一次回答通常會給出最可能的原因,但不一定命中。這時不要直接換問題,而是用追問法收斂。例如:

  • 「你說可能是資料來源缺欄位,我確認過資料庫都有 price,那還有什麼可能?」
  • 「這個錯誤只在生產環境出現,開發環境正常,這代表什麼?」
  • 「如果我加上 print(item) 在第 41 行,你預期會看到什麼?」

這種對話式除錯的關鍵,是把 AI 的假設一個一個驗證掉。每次你提供新的觀察(例如 log 輸出),AI 就能排除錯誤假設,逐步逼近真相。這其實就是科學方法:提出假設,設計實驗,觀察結果,修正假設。

第四步:讀懂常見錯誤類型

不同語言的錯誤有固定模式,讓 AI 幫你歸類會更快。以下整理幾種高頻錯誤與它們的典型根因:

錯誤類型 常見語言 典型根因
NullPointerException / undefined is not an object Java, JavaScript 存取了尚未初始化或已被清空的物件
KeyError / KeyNotFound Python, C# 存取字典中不存在的鍵
IndexOutOfRange 多數語言 陣列索引超出長度,常見於迴圈邊界
Connection refused / timeout 網路相關 服務未啟動、埠號錯誤或防火牆阻擋
CORS error 前端 後端未設定允許跨來源請求
Segmentation fault C, C++ 存取非法記憶體位址

把錯誤類型告訴 AI,再附上你的程式碼,它就能針對這一類的典型陷阱去檢查。例如遇到 Connection refused,好的 AI 會反問你「服務有啟動嗎?埠號對嗎?」而不是直接改程式。

第五步:驗證 AI 的修法,不要照單全收

這是最重要的一步。AI 會給出看起來合理的修法,但它可能治標不治本,甚至引入新問題。回到前面的 KeyError 例子,AI 可能建議:

total = sum(item.get('price', 0) for item in cart)

get 加預設值確實不會再拋錯,但這是對的修法嗎?如果某商品沒有 price 是資料錯誤,那把它當成 0 元只是把 bug 藏起來,帳目會對不上。正確的做法可能是:在資料進入購物車時就驗證欄位,或在缺欄位時明確拋出有意義的錯誤。

所以每次拿到 AI 的修法,要問自己三個問題:這是治本還是治標?它會不會讓錯誤靜默消失?有沒有測試能證明它真的修好了?必要時請 AI 一起補上單元測試來驗證。

實戰範例:一個非同步的競態條件

來看一個較難的例子。有段 JavaScript 程式偶爾會回傳舊資料:

let cache = null;

async function getUser(id) {
  if (!cache) {
    cache = await fetchFromAPI(id);
  }
  return cache;
}

把它連同「每次傳不同 id 卻拿到同一個 user」的現象貼給 AI,好的助手會指出兩個問題:第一,cache 用單一變數卻服務不同 id,第二個 id 的請求會拿到第一個的快取。第二,多個請求同時進來時,if (!cache) 判斷與賦值之間有競態視窗。這種「讀懂現象背後的並發模型」正是 AI 除錯發揮價值之處,因為它能一次考慮多個面向,而人在疲勞時容易只看到其中一個。

常見陷阱

第一個陷阱是資訊不足。只貼一行錯誤訊息,AI 只能猜。第二個陷阱是過度信任,把 AI 的話當成絕對正確而不驗證。第三個陷阱是貼上敏感資訊,例如 API 金鑰、資料庫密碼、真實用戶個資,除錯前務必先把這些遮蔽或替換成假資料。第四個陷阱是忽略版本差異,AI 的訓練資料可能是舊版框架,遇到新版 API 時要主動告知版本號。

小結

用 AI 除錯的核心,不是把問題丟出去等答案,而是把 AI 變成放大你觀察力的工具。先自己讀懂錯誤結構,給足上下文,用追問收斂假設,最後嚴格驗證修法。掌握這套流程後,你會發現除錯速度明顯提升,而且更能理解問題的根因,而不只是讓紅字消失。

常見問題

把公司程式碼貼給 ChatGPT 或 Claude 除錯安全嗎?

要看你使用的方案與資料政策。一般消費者版可能會用對話內容改善模型,企業版或 API 通常有不留存訓練的選項。無論如何,除錯前都應移除 API 金鑰、密碼、真實個資與商業機密,可用假資料重現同樣的錯誤結構再貼上。

AI 給的修法看起來能跑,但我不確定對不對怎麼辦?

請 AI 說明這個修法的原理,並追問它是治本還是治標,會不會讓錯誤靜默消失。最可靠的做法是請它一併寫出能重現該 bug 的單元測試,先看到測試失敗,套用修法後測試通過,才算真正修好。

堆疊追蹤很長,該全部貼給 AI 還是只貼重點?

建議全部貼上。堆疊追蹤的呼叫鏈能讓 AI 理解錯誤是從哪一層傳上來的,只貼最後一行會遺失關鍵脈絡。如果訊息含大量框架內部的行號,可以保留但告訴 AI 你的程式進入點在哪個檔案。

為什麼同一個錯誤,AI 每次給的原因不一樣?

因為你給的上下文不足,AI 只能在多個可能中猜測,每次抽到不同答案。解法是補足環境資訊、相關程式碼與實際觀察到的現象,並用追問逐一排除假設,把可能性收斂到唯一根因。

AI 找不出原因時該怎麼推進?

提供更多觀察資料,例如加上 log 或 print 後的輸出、在不同環境的重現狀況、最近一次可正常運作的版本與這次的差異。把除錯當成對話,每輪都餵新證據,AI 就能協助你縮小範圍,而不是重複猜測。