401 Unauthorized — 多半不是你剛換掉的那把 Key
- 確認端點要的是哪個頭:ANTHROPIC_AUTH_TOKEN 發
Authorization: Bearer,ANTHROPIC_API_KEY 發x-api-key——設錯了 Key 是好的也會 401。 env | grep -i anthropic看有沒有舊值蓋住新值,然後重啟客戶端(只在啟動時讀一次)。- 用 curl 發同樣請求:curl 通了但客戶端 401 = 客戶端沒讀到你以為的變數;curl 也 401 = 憑證或端點的問題。
客戶端連到相容端點時,中間有兩層各自獨立的認證,401 可能來自其中任何一層,而兩者的報錯文字一模一樣。重新生成自己的 Key 只處理得到其中一層——而且實際上那是比較少見的那一層。
你看到的報錯
API Error: 401 {"type":"error","error":{"type":"authentication_error","message":"invalid x-api-key"}}
401 Unauthorized
Could not resolve authentication method. Expected either apiKey or authToken to be set.
{"error":{"message":"Invalid bearer token","type":"authentication_error"}}
四種都只表示「請求送到了,但伺服器不接受它帶的憑證」。沒有一種會告訴你是哪一層拒絕的——但措辭可以縮小範圍。
| 資訊 | 它告訴你的事 | 最可能的原因 |
|---|---|---|
invalid x-api-key | 伺服器讀到了 x-api-key 頭並拒絕了它的值 | Key 不對——或者端點要的是 Bearer token |
Invalid bearer token | 伺服器讀到了 Authorization: Bearer 並拒絕了它的值 | Token 不對——或者端點要的是 x-api-key |
Could not resolve authentication method | 客戶端在發出任何東西之前就放棄了 | 兩個變數都沒設,或不是這個客戶端讀的那個 |
只有 401,沒有內容 | 有東西拒絕了它,而且沒有解釋 | 你不知道它在路徑上的某個代理或閘道器 |
兩層認證
| 誰對誰認證 | 失敗時的表現 | 誰能修 | |
|---|---|---|---|
| 第一層 | 你的客戶端 → 端點 | 第一次請求就失敗,每次都失敗 | 你 |
| 第二層 | 端點 → 它的上游供應商 | 常是間歇性的,或在完全沒改配置時突然開始 | 端點運營方 |
多數排錯文章只寫得到第一層——「檢查你的 Key」。這建議沒錯,但它解釋不了真正讓人困惑的那種情況:一小時前還好好的,而你什麼都沒動。出現這種情況時,問題不在第一層。
按這個順序排查
1 · 憑證真的進到請求裡了嗎#
複製貼上會夾帶看不見的東西——結尾換行、不換行空格、從聊天視窗帶出來的彎引號。
printf '%s' "$ANTHROPIC_AUTH_TOKEN" | wc -c
printf '%s' "$ANTHROPIC_AUTH_TOKEN" | tail -c 20 | xxd | tail -2
位元組數比看得見的長度多一,就是結尾跟著個換行一起被複制進來了。
2 · 你設的變數,產生的是端點要的那個頭嗎#
這是四種裡最安靜的一種失敗,因為報錯資訊完全不會提示你。
| 變數 | 客戶端發出的請求頭 |
|---|---|
ANTHROPIC_API_KEY | x-api-key: <值> |
ANTHROPIC_AUTH_TOKEN | Authorization: Bearer <值> |
如果端點是靠 Authorization: Bearer 認證,而你設的是 ANTHROPIC_API_KEY,請求送達時根本沒有 Authorization 頭。伺服器回 401,資訊說 Key 無效。Key 是好的,錯的是頭。反過來也會發生。
接 9Coding 時設 ANTHROPIC_AUTH_TOKEN,Key 以 sk-9c- 開頭。
3 · 你的 base URL 結尾,是客戶端預期的位置嗎#
客戶端會自己在你給的 base URL 後面接上路徑(/v1/messages、/v1/chat/completions)。如果你配的 base URL 結尾已經帶了 /v1,請求就會打到 /v1/v1/messages。這通常回 404——但先認證再路由的閘道器會回 401。
echo "$ANTHROPIC_BASE_URL"
正確的值就是 https://api.9coding.com——結尾不要斜槓,不要帶 /v1。
4 · 有沒有舊值蓋住了你剛設的#
寫在 shell 配置檔案裡的值、寫在專案配置檔案裡的值、以及當前這個 shell 裡的值,是三件不同的事。客戶端讀的是其中一個,你改的可能是另一個。
env | grep -i anthropic
每一條都要看,不要只看你記得設過的那條。然後重啟客戶端——Claude Code 只在啟動時讀一次環境變數,長時間執行的程序會沿用它啟動時的環境。
5 · 把客戶端排除在外#
curl -s -w '\n%{http_code}\n' https://api.9coding.com/v1/models \
-H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN"
- curl 回 200、客戶端回 401 → 客戶端讀的不是你以為的那個變數,回到第 4 步。
- curl 也回 401 → 問題在憑證或端點,不在客戶端。
- curl 連狀態碼都拿不到 → 這不是認證問題,看連線錯誤。
什麼時候這不是你的問題
以下四點同時成立,就是第二層的事,你這臺機器上沒有東西要修:
- 今天早些時候還能用,
- 你沒有改任何配置,
- 指向同一個端點的其他客戶端也是一樣的錯,
- 而且過一陣子會自己好。
在你自己的配置上再花一小時之前,先去看運營方的狀態頁與變更日誌。一個既不公開狀態頁也不公開變更日誌的端點,是你沒辦法排錯的端點——這件事本身就值得知道。我們的在狀態頁。
提問題時請帶上 request id——9Coding 的報錯響應裡都有一個,形如 (request id: 2026...)。這個 id 加上時間戳、模型名和完整報錯文字,就能把那一次呼叫查出來。只說「用不了」的反饋沒法排查。
401 和 403 不是同一個問題
403 表示請求透過了認證然後被拒絕:賬號沒有那個模型、那個地區或那個功能的許可權。換 Key 保證沒用。見 403 Forbidden。
相關報錯
- 403 Forbidden — 透過認證但沒有許可權
- TLS 證書錯誤 — 為什麼它第一次就失敗且不會重試
- 連線錯誤 — 分辨網路、代理與端點
- 全部報錯速查 — 排查手冊總表