博客

LLM API 返回 403:地區攔截、許可權與策略拒絕

LLM API 的 403 是四個不同問題擠在同一個狀態碼下:地區策略、許可權範圍、策略拒絕,或你自己路徑中的邊緣攔截。每一類的修法都不同,而重試不屬於任何一種。

LLM API 返回 403:地區攔截、許可權與策略拒絕

在 LLM 整合中,403 是最容易被誤讀的狀態碼。當運維手冊以 LLM request failed: 403 這一行開頭時,人的直覺是把它當成打錯號碼的限流,或者一次重試就能清掉的認證小毛病。兩者都不對。這個狀態碼覆蓋四類完全不同的問題:地區策略攔截、憑據許可權範圍、策略與內容拒絕,以及在請求到達提供商之前、發生在你自己網路路徑裡的攔截。每一類的修法都不同,而對這四類來說,重試都是錯誤的第一反應。本文是針對單一狀態碼的深入解析,承接完整錯誤碼排查;如果你是從 429 過來的,關於可重試限制的姊妹篇是速率限制指南。

LLM API 403 forbidden 不只是一個錯誤

在開始診斷之前,先把這四類的定義記牢,因為本文餘下全部內容都是在區分它們。

  1. 地區與屬地攔截。請求來自提供商不服務的地區,拒絕出於策略,而非故障。
  2. 憑據許可權範圍。金鑰有效且被識別,但不被允許在這裡做這件特定的事。
  3. 策略與內容拒絕。請求本身不被允許,與是誰在發起無關。
  4. 閘道器、代理與邊緣攔截。你自己路徑中的某個環節(企業出口管控、自建閘道器、安全產品)代替提供商作出了回應。請求從未到達。

注意缺了什麼:這份清單上沒有任何一項是暫時性狀況。正是這一點決定了第一條規則。

規則一:401 問你是誰,403 問你被允許做什麼

人們常把 401 和 403 當作可以互換的一對,而錯誤表比口口相傳的講法更清楚地劃出了這條界線。OpenAI 的錯誤參考列出了與身份和組織相關的 401 情形:認證無效、金鑰不正確、賬號不屬於任何組織,以及請求 IP 與已配置的允許列表不符。Anthropic 的錯誤表在其一側為認證問題畫出了同樣的形狀。而 403 這一族關乎的是授權:*** 許可權範圍,以及策略。這個區別重要,因為修法位於不同地方:身份問題在你的憑據配置裡解決( Claude Code 憑據優先順序那篇文章講的就是那邊多個憑據如何相互作用),而授權問題要在許可權、策略或位置中解決。一個有用的簡記法:401 意味著門不認識你;403 意味著門清楚知道你是誰,但仍然關著。

這就引出本文想要陳述的操作規則:不要把退避重試邏輯用在 403 上。速率限制指南里那套重試機制是為會自行變化的狀況準備的;403 是一個決定,而決定不會隨定時器到期。重試地區攔截或許可權拒絕,只是花著額度重問一個答案早已存檔的問題。

四類 403,逐一拆解

地區與屬地策略

OpenAI 在其錯誤表裡把這一條目標為 403 - Country, region, or territory not supported,原因寫得很直白:你正從不被支援的國家、地區或屬地訪問該 API,解決方案則指向受支援國家頁面。這一點值得讀兩遍:提供商把它當作帶文件憑據的策略邊界,而不是 bug。處理路徑也由此而來。去提供商的頁面上確認位置策略(對於你正在閱讀本文的這個平臺,對應的頁面是我們自己的受支援地區頁面),如果你的情況需要例外處理或正式答覆,路徑要經過提供商的官方渠道:客戶代表或支援團隊。這是一場關於合規與賬號的對話,也是唯一一類把“改你的程式碼”當作答案完全跑偏的 403。

憑據許可權範圍

第二類看起來像認證問題,實則是授權問題:*** 沒有問題,許可權有問題。OpenAI 的文件在認證故障排查中處理了這一情形,把“API key 不具備該端點所需許可權”列在原因之中,並將解決方向指向金鑰、組織 ID 和專案級金鑰。在 SDK 層,同樣的情形表現為 PermissionDeniedError,其文件給出的原因是對所請求資源沒有訪問許可權,給出的解決辦法是檢查 API key、組織 ID 和資源 ID。Anthropic 在錯誤表裡直接點名了這一情形:403 permission_error,意為該 API key 無權使用指定資源,修復路徑是控制台裡你所在組織的訪問設定與工作區設定。所以端點上的 API key permission denied 是一個配置問題,對應一份具體的清單:對的金鑰、對的組織、對的工作區、對的資源 ID。如果這些都核對無誤而拒絕依舊,下一步是找到能在提供商側檢視訪問設定的管理員。

策略與內容拒絕

並非每個 403 都關乎訪問許可權;有些是平臺拒絕了請求本身。這一類與其他 4xx 家族有交集,需要劃清邊界:400 類校驗錯誤意味著請求格式有誤,模型側的拒答是模型在一個成功的響應內部表示拒絕,而策略拒絕是平臺拒絕執行該操作。對這一類,實用的第一步始終相同:讀錯誤響應正文。兩個生態都會返回帶有 type 和 message 的結構化錯誤,因此在你給狀態碼賦予含義之前,type 欄位已經告訴你身處哪個家族。然後去讀管轄你所嘗試動作的策略文件,而不是反覆改 prompt 碰運氣。如果請求觸發了策略邊界,prompt 工程不是工具,讀規則才是。

閘道器、代理與邊緣攔截

第四類根本到不了提供商,這正是它的特徵。自建閘道器、企業出口鏈路、CDN 或安全裝置都可能用自己的 403 形式拒絕請求。診斷靠形狀:API 錯誤響應是帶 error 物件、type、message 和 request ID 的 JSON;邊緣攔截通常返回別的東西——HTML 頁面、一行純文本、某種廠商特有的結構,而且沒有 request ID,因為根本沒有請求存在。Anthropic 的文件甚至從提供商側展示了這個概念:它指出在其某一錯誤情形下,響應是在請求到達 API 伺服器之前由邊緣基礎設施返回的,這正是要找的模式。修法屬於網路考古,而非賬號操作:比較一次直連呼叫與一次走完整路徑的呼叫,把兩份原始響應都留作證據,並與負責中間環節的人一起處理。

一條可以按序執行的判斷路徑

  1. 讀響應正文,而不只是狀態碼。 先把其中error.type 和error.message 這兩項寫進事故記錄。
  2. 檢查有沒有 request ID。如果正文和響應頭裡都沒有,先懷疑第四類,而不是第一類。
  3. 歸入四類之中。地區、許可權、策略或邊緣。
  4. 地區類:先查策略頁面,其次走官方渠道。沒有別的路徑。
  5. 許可權類:按順序複核金鑰、組織、工作區、資源 ID,然後轉給管理員。
  6. 記錄結論。屬於哪一類、有哪些證據、改動了什麼。這條記錄應包含的欄位清單(含 request ID)屬於日誌指南的範疇,也正是它讓下一次發生從謎團變成查表。

支援工單裡該附上什麼

兩家廠商都圍繞同一件東西設計:request ID。Anthropic 的指引明確說每個響應都包含唯一的 request-id 頭,同一個識別符號也會出現在錯誤正文的 request_id 欄位中,並且支援溝通中應當包含它。OpenAI 的錯誤參考則要求你在升級一個持續存在的錯誤時,提供你傳送的請求資料與請求頭。升級時請附上:request ID;UTC 時間戳;端點與模型;完整的錯誤型別與訊息;這次呼叫是否經過任何閘道器;復現步驟;以及你已經排除了什麼。這份清單刻意顯得乏味,而它決定了工單是推進還是被退回。

把合規邊界說清楚

對 AI 服務的地區限制,是廠商在真實法律約束下作出的策略與合規決定,與它們打交道的唯一持久方式,就是通過作出這些決定的同一批官方渠道:受支援地區文件,以及在你需要例外或澄清時的廠商支援或客戶團隊。本文刻意不討論、不支援、也不暗示任何規避地區限制的方法,因為這些做法都不可靠,而且都會讓賬號、資料與商業關係承擔風險。如果你的團隊處在受限地區,有價值的對話是關於官方支援的路徑:廠商在那裡提供什麼、必須執行的工作負載有什麼替代方案、文件今天怎麼說。這場對話,連同你的客戶團隊與法律顧問,也是唯一能產出你在審計中站得住腳的答案的那場對話。

本文的位置

本文屬於一個診斷系列。完整的錯誤碼排查勾勒了每個狀態碼家族;本文是其中之一的深入解析。重試指南說明何時重試才是對的,而本文的 403 規則正是刻意針對這個狀態碼與它相反的。日誌指南提供了上文中用到的證據欄位。而當你呼叫的端點位於某個相容介面之後時,端點層面的事實就寫在平臺自己的文件。

403 檢查清單

  1. 先分類:地區、許可權、策略還是邊緣。
  2. 確認來源:帶 request ID 的 API 錯誤正文說明來自提供商;沒有則指向路徑。
  3. 地區類:只走策略頁面與官方渠道。沒有例外,也不耍聰明。
  4. 許可權類:按順序核對金鑰、組織、工作區與資源 ID。
  5. 策略類:在動 prompt 之前,先讀錯誤型別與管轄該動作的策略文件。
  6. 邊緣類:比較直連與走完整路徑的響應,並把兩者都留作證據。
  7. 按證據清單升級,request ID 放在最前面。
  8. 永遠不要對 403 做退避重試;並且在本地、流水線和生產環境中對同一個金鑰建立基線,因為第四類恰恰藏在這些差異裡。

四個問題,一個狀態碼,一條紀律:讀正文、找分類、修對那一層。在真正要緊的時候,乏味的診斷永遠勝過聰明的重試。