This article is not yet available in English. You are reading the Traditional Chinese original. The English edition will appear here once it is translated.
Browse articles that do have an English edition怎麼讀一則錯誤訊息:解剖、堆疊追蹤與結束代碼
新手看錯誤訊息的方式幾乎都是同一種:從第一行開始,逐字讀,讀到第二十行發現自己一個字都沒看懂,然後關掉視窗、重裝。
問題不在你讀不懂英文,也不在你不懂程式。問題在沒有人告訴過你這則訊息有形狀。
它有。而且形狀很固定:
| 位置 | 是什麼 | 對你的價值 |
|---|---|---|
| 最後一行(或最後幾行) | 結論 | 最高。九成的時候你要的答案就在這裡 |
| 中間一大段 | 堆疊追蹤(stack trace) | 低,但有一個例外,見下 |
| 散在中間與結尾 | 檔名與行號 | 高。有行號就直接去看那一行 |
| 最後,常常被忽略 | 結束代碼(exit code) | 高。它告訴你「到底成功了沒有」,比輸出文字誠實 |
這篇教你怎麼按這個順序拆一則你完全看不懂的訊息。
四步驟的短版、以及七種常見結尾行對照表,在 Terminal、Shell、CLI:三個詞的差別 裡已經有一份。這篇不重複那張表 —— 這裡講的是那張表背後的原則:為什麼是倒過來讀、堆疊追蹤到底在說什麼、以及拿到一則訊息之後你該把它給誰。
步驟
步驟一:捲到最後,只讀最後一行
不管這則訊息有多長,先做這一件事:捲到最底部。
多數工具把結論放在最後。原因是它一路做下來,做到某一步失敗了,然後把失敗的原因印出來收尾。中間那一大段是過程紀錄,結尾才是它的判斷。
最後一行通常很短。抄下來。它幾乎一定會落在下面幾種形狀之一:
- 一句英文的結論,例如
No such file or directory、Permission denied、command not found - 一個類別名稱加一句話,例如
ModuleNotFoundError: No module named 'requests' - 一個三位數的數字,例如
401、403、429 - 一個全大寫的底線分隔識別碼,例如
UnauthorizedAccess、EACCES、ENOTFOUND
這一行的資訊量,通常比前面三十行加起來還高。
步驟二:往上找第一個 Error、error: 或 failed
從最後一行往上捲,找第一個出現這些字樣的地方。
為什麼是「第一個」而不是「最後一個」:很多工具在真正失敗之後,還會印一段收尾訊息、一段「請參考文件」、或一段上層呼叫端的抱怨。上層的抱怨只是轉述,第一個出錯點才是原因。
舉例(這是範例,不是任何工具的真實輸出):
[1/4] Reading config... ok
[2/4] Resolving dependencies... ok
[3/4] Fetching package foo==1.2.0
error: failed to fetch https://registry.example.invalid/foo-1.2.0.tar.gz
caused by: connection refused
[4/4] aborted
See https://example.invalid/docs/troubleshooting for help.
倒著讀的人會先看到第 4 行的 aborted(沒資訊量)與最後那行文件連結(也沒資訊量)。真正的原因在 error: 那一行,而它的下一行 caused by: 給了你更精確的版本 —— caused by 這個詞後面接的,幾乎永遠比它前面那句有用。
步驟三:找檔名與行號
在整段訊息裡掃這兩個形狀:
File "app.py", line 42, in main
src/main.ts:17:5
/path/to/script.sh: line 8: foo: command not found
三種分別是 Python、TypeScript/很多編譯器、以及 shell 腳本的寫法,但結構一樣:哪個檔案、第幾行。
src/main.ts:17:5是「第 17 行、第 5 個字元」script.sh: line 8是「第 8 行」
有行號就直接去開那個檔案、看那一行。 這比讀懂整則訊息快得多,而且你不需要看懂訊息也能做。
如果那個檔案不是你的(路徑在某個套件庫或系統目錄底下),那行號對你沒有用 —— 這代表錯誤發生在你呼叫的別人的程式碼裡面,你要看的是你自己那一行是怎麼呼叫它的,也就是堆疊追蹤裡下一個屬於你的檔案。這就接到下一段。
步驟四:讀堆疊追蹤,由下往上
堆疊追蹤(stack trace)是新手最容易被淹沒的一段。它長這樣(範例):
Traceback (most recent call last):
File "/Users/you/project/main.py", line 12, in <module>
result = load_config(path)
File "/Users/you/project/config.py", line 34, in load_config
return json.loads(text)
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/json/__init__.py", line 346, in loads
return _default_decoder.decode(s)
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/json/decoder.py", line 338, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 7 column 3 (char 112)
為什麼要由下往上讀。
堆疊追蹤列的是「呼叫鏈」:最上面是你程式的入口,往下每一層是被上一層呼叫的函式,最下面那一層是執行到一半真正出事的地方。所以:
- 最後一行(最底層)是結論:
JSONDecodeError: Expecting ',' delimiter: line 7 column 3。它告訴你:某個 JSON 檔案第 7 行第 3 個字元少了逗號。 - 從下往上找第一個「你自己的檔案」:上面那個範例裡是
config.py第 34 行。這是你需要打開的檔案。 - 中間那些框架與標準函式庫的路徑,全部跳過。 那不是你的程式碼,你也改不了它。看不懂不是你的問題。
一句話版本:最底層告訴你「錯在哪」,往上第一個屬於你的檔案告訴你「去改哪」。
這個讀法對 Python、JavaScript、Java、Go、Rust 都成立,雖然措辭不同(JavaScript 寫 at functionName (file:line:col),而且順序相反 —— 最上面才是出事的地方)。所以先認一件事:你手上這則是哪種語言的。認不出來就看檔名副檔名(.py、.js、.ts、.go)。
步驟五:看結束代碼,確認它到底成功了沒有
這是多數新手從來沒看過的一個數字,而它是整則訊息裡最誠實的部分。
結束代碼(exit code)是程式結束時交回的一個整數:0 代表成功,非 0 代表失敗。見 Exit Code(結束代碼)。
在 macOS/Linux 的 shell 裡,跑完一條指令之後立刻:
echo $?
Windows PowerShell:
$LASTEXITCODE
為什麼這個數字比輸出文字可靠:一個程式可以印出一大堆看起來完全正常的進度訊息,然後以非 0 結束;也可以刷一屏警告,結束代碼卻是 0。腳本、CI 系統、以及 AI Agent 判斷「上一步成不成功」,靠的都是這個數字,不是閱讀輸出文字。
這帶來一個非常實際的後果:如果你把一則錯誤訊息貼給 AI Agent 或貼到論壇,附上結束代碼,對方就知道該不該繼續往下追。 沒有這個數字,對方第一件事通常就是問你「它到底跑成功了沒有」。
順帶一個反直覺的點:echo $? 給的是上一條指令的結束代碼。所以你要在失敗的那條指令之後立刻跑它,中間不能插任何別的指令 —— 插了就被蓋掉。
步驟六:決定這則訊息要給誰
讀完上面五步,你手上有:最後一行、出錯的檔名與行號、結束代碼。現在做一個決定。
情況一:最後一行是一句你看得懂的英文結論。 把它整段(連同你跑的指令)拿去搜尋。加引號搜最後一行原文,比搜你自己的描述準得多 —— 因為別人的錯誤訊息跟你的一模一樣,而別人的描述跟你的不一樣。搜的時候補上工具名稱與版本號。
情況二:你看不懂最後一行,但你有檔名與行號。 直接去開那個檔案那一行。很多時候看一眼就知道(少一個逗號、拼錯一個名字、路徑寫錯)。這比搜尋快。
情況三:訊息很長、有多層 caused by、或涉及好幾個工具。
這是該貼給 AI Agent 的情況。原因很具體:Agent 能在你的機器上跑指令,它可以自己執行步驟一到五,不需要你轉述。你貼給搜尋引擎的是一段死文字,貼給 Agent 的是一個它可以動手調查的現場。
給 Agent 的時候,貼這些(缺一不可):
1. 我跑的完整指令(原樣貼上,不要改寫)
2. 完整的錯誤訊息(原樣貼上,不要節錄、不要翻譯)
3. 結束代碼
4. 作業系統與版本、以及工具的版本號
5. 我已經確認過什麼(例如:which 有印出路徑、磁碟還有空間、換過網路)
第 5 項最常被跳過,而它最省時間 —— 沒有它,Agent 會從頭問一遍你已經做過的事。
情況四:訊息裡有密鑰、密碼、或公司內部網址。 先塗掉再貼給任何人。 錯誤訊息常常會把環境變數的內容印出來,因為它出現在指令參數或設定檔裡。這件事在 API Key 是什麼 裡有完整的說明 —— 貼出去的密鑰要當作已經洩漏處理,光刪掉那則發文沒有用。
搜尋引擎、公開論壇、以及多數 AI 工具的對話內容,都不該出現你的密鑰。
六個真實形狀的範例
以下都是教學用的示意範例,形狀取自常見工具的真實輸出結構,但內容是編的。認形狀,不要背字。
一、指令不存在(PATH 問題)
bash: somecli: command not found
一行,沒有堆疊追蹤。這是 shell 自己在講話,不是那個程式在講話 —— 因為那個程式根本沒被找到。第一個動作是 which somecli,不是重裝。見 PATH 與路徑。
二、檔案不存在,但指令存在
cat: notes.txt: No such file or directory
九成不是檔案消失了,是你站的資料夾不對。先 pwd。見 Working Directory(工作目錄)。
三、權限
chmod: changing permissions of 'run.sh': Operation not permitted
或更常見的:
bash: ./run.sh: Permission denied
兩個看起來像,其實不同。第二個通常只是檔案缺可執行權限,chmod +x run.sh 就解決,跟 sudo(管理員權限) 一點關係都沒有。先 ls -l run.sh 看權限位。見 File Permission(檔案權限)。
四、Node.js 找不到模組(堆疊追蹤由上往下讀的那一種)
node:internal/modules/cjs/loader:1404
throw err;
^
Error: Cannot find module 'express'
Require stack:
- /Users/you/project/index.js
at Module._resolveFilename (node:internal/modules/cjs/loader:1401:15)
at index.js:3:17
注意這裡的結構跟 Python 相反:Error: Cannot find module 'express' 在上面,然後 at ... 一路往下是呼叫鏈。而 Require stack 那段直接告訴你是 /Users/you/project/index.js 第 3 行在要這個模組。
五、HTTP 狀態碼
{"error":{"message":"Incorrect API key provided","type":"invalid_request_error","code":"invalid_api_key"}}
配合結束代碼非 0。這類 JSON 格式的錯誤裡,code 與 type 欄位比 message 好用 —— message 是給人讀的句子,code 是給程式比對的固定字串,拿去搜尋命中率高得多。
401/403/429 這些數字各自的意思見 Status Code(狀態碼) 與 Rate Limit(速率限制)。
六、Windows PowerShell 的執行原則
.\install.ps1 : File .\install.ps1 cannot be loaded. The file .\install.ps1 is not
digitally signed. The script will not execute on the system.
+ CategoryInfo : SecurityError: (:) [], PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess
這是本站從 Microsoft 官方文件裡抄下來的真實輸出(不是示意)。注意最後那個 FullyQualifiedErrorId : UnauthorizedAccess —— 這是 PowerShell 的穩定識別碼,比上面那段句子更適合拿去搜尋。處理方式見 Windows 上安裝失敗 的步驟四。
三個讀錯誤訊息的壞習慣
一、只截圖,不複製文字。 截圖不能被搜尋、不能被 Agent 讀、也不能被別人複製那行關鍵字。終端機的文字是可以選取複製的(macOS 直接在視窗裡拖曳選取,Windows Terminal 也是)。永遠複製文字。
二、只看第一段就下結論。 第一段通常是進度訊息,不是錯誤。真正的結論在最後。
三、同一條指令重跑五次。 同樣的輸入會得到同樣的輸出。第二次之後你拿到的不是新資訊,是同樣的資訊加上你越來越焦躁的情緒。重跑之前先改一個變數 —— 換個資料夾、開個新視窗、換個網路 —— 否則你只是在浪費時間。
下一步
- 讀完之後要動手修:裝完沒反應:五個檢查,照順序做完再重裝
- 平台細節:Windows 上安裝失敗、macOS 上安裝失敗
- 常見結尾行對照表與十行保命指令:Terminal、Shell、CLI:三個詞的差別
- 那個視窗到底是什麼:Terminal 是什麼
- 結束代碼為什麼重要:Exit Code(結束代碼)、Process(處理程序)
- 一個真實的、從頭讀到尾的崩潰分析:一次 PEP 668 崩潰的完整分析
More in Learn
- Complete LangChain Tutorial 2026: Building Enterprise-Grade LLM Applications from Scratch
- MemoryHub v2.0 System Architecture In-Depth Analysis: From Capture Daemon to MCP Real-Time Memory Capture
- May 2026 LLM API Pricing Landscape: Complete Comparison of DeepSeek, Qwen, GLM, Kimi, MiniMax, and Doubao
- Cross-Channel Memory Hub: A Full Record of the Memory System Architecture Design for OpenClaw Agent