跳至主要內容
Skip to content

狀態碼寶典(下):4xx-5xx 客戶端與伺服器錯誤

上一篇我們學習了 1xx-3xx 狀態碼,本篇將完整解析 4xx(客戶端錯誤)和 5xx(伺服器錯誤)。這些狀態碼是開發和除錯過程中最常遇到的「老朋友」。


一、 4xx 客戶端錯誤

4xx 狀態碼表示「請求有問題,錯誤在客戶端」。伺服器無法處理請求,通常是因為請求格式錯誤、缺少認證或資源不存在。

400 Bad Request

含義:請求格式錯誤,伺服器無法理解

常見原因

  • JSON 格式錯誤(缺少引號、多餘逗號)
  • 必填參數缺失
  • 參數類型錯誤(需要數字但傳了字串)
  • URL 格式錯誤
http
POST /api/users HTTP/1.1
Content-Type: application/json

{"name": "John", "age": "not a number"}

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "error": "Bad Request",
  "message": "age must be a number",
  "field": "age"
}

TIP

回應 Body 應包含具體的錯誤原因,幫助開發者快速定位問題。

401 Unauthorized

含義:未提供認證憑證,或憑證無效

常見原因

  • 未攜帶 Token
  • Token 已過期
  • Token 格式錯誤
http
GET /api/users/me HTTP/1.1

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api"

{
  "error": "Unauthorized",
  "message": "Missing or invalid access token"
}

重點

  • 應包含 WWW-Authenticate 標頭,告知認證方式
  • 與 403 的區別:401 是「不知道你是誰」,403 是「知道你是誰,但你沒權限」

403 Forbidden

含義:伺服器理解請求,但拒絕執行

常見原因

  • 無權訪問該資源
  • IP 被封鎖
  • 帳號被停用
  • 資源被設為私有
http
DELETE /api/users/456 HTTP/1.1
Authorization: Bearer valid_token

HTTP/1.1 403 Forbidden

{
  "error": "Forbidden",
  "message": "You don't have permission to delete this user"
}

401 vs 403 比較

狀態碼含義情境
401未認證沒登入、Token 過期
403無權限已登入,但沒有權限

404 Not Found

含義:請求的資源不存在

常見原因

  • URL 路徑錯誤
  • 資源已被刪除
  • ID 不存在
http
GET /api/users/99999 HTTP/1.1

HTTP/1.1 404 Not Found

{
  "error": "Not Found",
  "message": "User with id 99999 does not exist"
}

NOTE

有時出於安全考慮,即使資源存在但無權訪問,也會回傳 404(避免洩漏資源存在的資訊)。

405 Method Not Allowed

含義:請求方法不被允許

http
DELETE /api/users HTTP/1.1

HTTP/1.1 405 Method Not Allowed
Allow: GET, POST

{
  "error": "Method Not Allowed",
  "message": "DELETE is not allowed on /api/users"
}

重點

  • 必須包含 Allow 標頭,列出允許的方法

406 Not Acceptable

含義:伺服器無法產生客戶端可接受的格式

http
GET /api/users HTTP/1.1
Accept: application/xml

HTTP/1.1 406 Not Acceptable

{
  "error": "Not Acceptable",
  "message": "This API only supports application/json"
}

408 Request Timeout

含義:伺服器等待請求超時

http
HTTP/1.1 408 Request Timeout

{
  "error": "Request Timeout",
  "message": "The server did not receive a complete request in time"
}

409 Conflict

含義:請求與伺服器當前狀態衝突

常見場景

  • 嘗試創建已存在的資源
  • 併發修改衝突
  • 違反唯一性約束
http
POST /api/users HTTP/1.1
Content-Type: application/json

{"email": "john@example.com", "name": "John"}

HTTP/1.1 409 Conflict

{
  "error": "Conflict",
  "message": "A user with this email already exists"
}

410 Gone

含義:資源曾經存在,但已永久移除

與 404 的區別:

狀態碼含義快取
404找不到(可能從未存在)不建議快取
410已永久刪除(曾經存在)可以快取
http
GET /api/posts/123 HTTP/1.1

HTTP/1.1 410 Gone

{
  "error": "Gone",
  "message": "This post has been permanently deleted"
}

413 Payload Too Large

含義:請求體超過伺服器限制

http
POST /api/upload HTTP/1.1
Content-Length: 104857600

HTTP/1.1 413 Payload Too Large
Retry-After: 3600

{
  "error": "Payload Too Large",
  "message": "File size exceeds the 10MB limit"
}

414 URI Too Long

含義:URL 超過伺服器限制

http
GET /api/search?q=very...long...query HTTP/1.1

HTTP/1.1 414 URI Too Long

TIP

使用 POST + Body 來傳遞大量查詢參數,而非全塞在 URL 中。

415 Unsupported Media Type

含義:不支援請求的 Content-Type

http
POST /api/users HTTP/1.1
Content-Type: application/xml

<user><name>John</name></user>

HTTP/1.1 415 Unsupported Media Type

{
  "error": "Unsupported Media Type",
  "message": "Only application/json is supported"
}

422 Unprocessable Entity

含義:請求格式正確,但語意錯誤(驗證失敗)

與 400 的區別:

狀態碼含義場景
400格式錯誤JSON 語法錯誤
422驗證失敗格式正確但內容不合法
http
POST /api/users HTTP/1.1
Content-Type: application/json

{"email": "not-an-email", "age": -5}

HTTP/1.1 422 Unprocessable Entity

{
  "error": "Validation Error",
  "details": [
    {"field": "email", "message": "Invalid email format"},
    {"field": "age", "message": "Age must be positive"}
  ]
}

429 Too Many Requests

含義:請求頻率過高,觸發限流

http
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1704700800

{
  "error": "Too Many Requests",
  "message": "Rate limit exceeded. Try again in 60 seconds"
}

重點

  • 應包含 Retry-After 標頭
  • 可包含 X-RateLimit-* 標頭提供更多資訊

二、 5xx 伺服器錯誤

5xx 狀態碼表示「伺服器發生錯誤」。問題在伺服器端,客戶端的請求可能是完全正確的。

500 Internal Server Error

含義:伺服器內部錯誤(萬用錯誤碼)

常見原因

  • 程式碼拋出未處理的異常
  • 資料庫連線失敗
  • 空指標引用
http
HTTP/1.1 500 Internal Server Error

{
  "error": "Internal Server Error",
  "message": "An unexpected error occurred",
  "requestId": "abc-123-def"
}

CAUTION

不要在 5xx 回應中暴露堆疊追蹤或敏感資訊!只應包含請求 ID 供日誌查詢。

501 Not Implemented

含義:伺服器不支援請求使用的功能

http
TRACE /api/users HTTP/1.1

HTTP/1.1 501 Not Implemented

{
  "error": "Not Implemented",
  "message": "TRACE method is not implemented"
}

502 Bad Gateway

含義:作為網關或代理的伺服器,從上游收到無效回應

常見原因

  • 後端服務掛了
  • 後端服務回應格式錯誤
  • 網路問題

503 Service Unavailable

含義:伺服器暫時無法處理請求

常見原因

  • 維護中
  • 過載
  • 正在部署
http
HTTP/1.1 503 Service Unavailable
Retry-After: 300

{
  "error": "Service Unavailable",
  "message": "Server is under maintenance. Please try again in 5 minutes"
}

重點

  • 應包含 Retry-After 標頭
  • 這是暫時的,與 500 的「可能需要修復」不同

504 Gateway Timeout

含義:網關或代理等待上游伺服器超時

與 408 的區別:

狀態碼誰超時
408伺服器等待客戶端超時
504代理等待後端超時
http
HTTP/1.1 504 Gateway Timeout

{
  "error": "Gateway Timeout",
  "message": "Upstream server took too long to respond"
}

三、 錯誤回應最佳實踐

3.1 統一錯誤格式

建議使用一致的錯誤回應結構:

json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "One or more fields are invalid",
    "details": [
      {
        "field": "email",
        "code": "INVALID_FORMAT",
        "message": "Email format is invalid"
      }
    ],
    "requestId": "req-abc-123"
  }
}

3.2 錯誤分類與處理

3.3 指數退避重試

對於 5xx 錯誤,建議使用指數退避策略:

javascript
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(url, options);

      if (response.status >= 500) {
        throw new Error(`Server error: ${response.status}`);
      }

      return response;
    } catch (error) {
      if (i === maxRetries - 1) throw error;

      // 指數退避:1s, 2s, 4s...
      const delay = Math.pow(2, i) * 1000;
      await new Promise((resolve) => setTimeout(resolve, delay));
    }
  }
}

四、 實用速查表

4xx 系列

狀態碼名稱常見場景
400Bad Request參數錯誤、JSON 格式錯誤
401Unauthorized未登入、Token 無效
403Forbidden無權限
404Not Found資源不存在
405Method Not Allowed方法不支援
409Conflict資源衝突
410Gone資源已永久刪除
413Payload Too Large上傳檔案太大
415Unsupported Media TypeContent-Type 不支援
422Unprocessable Entity驗證失敗
429Too Many Requests觸發限流

5xx 系列

狀態碼名稱常見場景
500Internal Server Error伺服器內部錯誤
501Not Implemented功能未實作
502Bad Gateway後端服務無響應
503Service Unavailable維護中、過載
504Gateway Timeout後端超時

總結

類別含義客戶端行為
4xx客戶端錯誤檢查請求、修正後重試
5xx伺服器錯誤等待、重試,或聯繫支援

> **記憶口訣**:

  • 4xx = 「你的錯」
  • 5xx = 「我的錯」

選擇狀態碼的原則

  1. 精確優先:選擇最能描述問題的狀態碼
  2. 安全考慮:必要時用 404 取代 403,避免洩漏資訊
  3. 一致性:整個 API 使用統一的錯誤格式
  4. 可操作性:提供足夠的資訊讓客戶端知道如何處理

進階挑戰

  1. 設計一個完整的錯誤回應格式,包含錯誤碼、訊息、欄位驗證錯誤、請求 ID。在什麼情況下應該包含哪些資訊?
  2. 思考:為什麼有些網站會在用戶登入失敗時回傳「帳號或密碼錯誤」而不是明確指出是哪個錯了?這算 400 還是 401?
  3. 實作一個帶有指數退避的 HTTP 客戶端,對 5xx 錯誤自動重試最多 3 次。

延伸閱讀與資源