エラー処理とステータスコード
1)エラーを標準化する理由
1つのエラーコントラクトでクライアントのデバッグを高速化し、偽のリトレイを削減し、RCAを再生可能にします。よいシステム:- 予測可能に問題の種類をエンコードし、
- クライアントに有効なプロンプト(次に何をすべきか)を与えます),
- 内部部品の漏出から保護します、
- retrasおよびidempotencyと互換性がある。
2)設計原則
1.すべてのサービスに1つのエラースキーム(REST/GraphQL/gRPC/webhooks)。
2.リトレイの明確な意味:どのコードを引き込むか、そうでないか。
3.書き込み操作でフェイルクローズ:静かな不整合よりも優れた4xx/5xx。
4.リークなし:SQL、スタック、コンフィギュレーション、内部IDを開示しないでください。
5.Trace-常に'trace_id'/'correlation_id'を返します。
6.メッセージのローカライズは任意ですが、コードと'reason'は安定しています。
3)シングルフォーマット(問題詳細/JSON)
推奨ベースフォーマット(RFC 7807準拠):json
{
"type": "https://errors.example.com/auth/invalid-token",
"title": "Invalid access token",
"status": 401,
"code": "AUTH_INVALID_TOKEN",
"detail": "Token expired or signature invalid.",
"instance": "/api/v1/payments/12345",
"trace_id": "01HX3...ABC",
"hint": "Obtain a new token via OAuth2 refresh.",
"meta": {
"scope": "payments:write",
"policy": "deny-by-default"
}
}
説明:
- 'type'は安定したエラークラスURLです。
- 'code'-短いドメインマシンコード(リリース間で安定)。
- 'hint'-クライアントのために何をすべきか(繰り返し、トークンの更新、パラメータの変更)。
- 'meta'-安全な部品(秘密とPIIなし)。
4)ステータスコードマップ(最低セット)
認証/承認
400 Bad Request-構造検証/スキーム。
401無許可-いいえ/無効なトークン。'WWW-Authenticate'を追加します。
403 Forbidden-認証されていますが、権利/ポリシーは拒否されません。
404 Not Found-権利のないリソースの存在をマスクします。
409競合-バージョン/状態競合(楽観的ロック、idempotency)。
451法的理由で利用できない-コンプライアンス/管轄ブロック。
制限と保護
408リクエストタイムアウト-クライアントはゆっくりと本体を送信しています。
409/425早すぎる-0-RTT/TLSでの早期反復の禁止1。3.
429リクエストが多すぎる-'Retry-After'とリミットポリシー。
499 Client Closed Request-(周囲/NGINXで)クライアントは接続を切断しました。
データおよびビジネスルール
422 processable Unprocessable Content-ビジネス検証がスキームを渡しましたが、意味が間違っています。
423ロック-リソースのブロック(KYCレビュー、AMLフリーズ)。
409競合-二重提出、レース、ステータス制限(「すでにプロセス中」など)。
410 Gone-エンドポイント/リソースが削除されました(非推奨の完了)。
サーバー
500内部サーバーエラー-不明なエラー;詳細は明らかにしていません。
502 Bad Gateway-依存関係がエラー/プロキシを返しました。
503サービス利用不可-劣化/計画された作業;'Retry-After'を追加します。
504ゲートウェイタイムアウト。
5)リトレイとidempotencyセマンティクス
400/ 401/403/404/422を引き出すことはできません(顧客が要求を変更しない限り)。
408/429/5xx/ 425/499/504(バックオフ+ジッタ付き)を引き込むことができます。
Idempotency: 'POST'の場合、'Idempotency-Key' (UUIDv4)を有効にします。
再試行の競合については、'hint: Use same Idempotency-Key or GET status'で409を返します。
保存した結果を返すときに'Idemotency-Replay: true'を追加します。
HTTP/1.1 429 Too Many Requests
Retry-After: 3
RateLimit-Limit: 50
RateLimit-Remaining: 0
RateLimit-Reset: 1730641030
6)入力検証: フィールドエラー構造
400/422では、フィールドエラーの配列を使用します:json
{
"type": "https://errors.example.com/validation",
"title": "Validation failed",
"status": 422,
"code": "VALIDATION_ERROR",
"trace_id": "01HX4...XYZ",
"errors": [
{"field": "amount", "rule": "min", "message": "Must be >= 10"},
{"field": "currency", "rule": "enum", "message": "Unsupported currency"}
]
}
7)部分的な失敗(バッチ/部分的な失敗)
バッチエンドポイントでは、構造なしで200内のエラーを隠さないでください。結果の配列を持つ207マルチステータスまたは200を返します。各タスクには独自のステータスがあります:json
{
"status": "partial",
"succeeded": 8,
"failed": 2,
"results": [
{"id": "op1", "status": 201},
{"id": "op2", "status": 422, "error": {"code":"VALIDATION_ERROR","detail":"..."}}
]
}
8)ペジネーションと「空白」の回答
空のコレクション-200秒のアイテム:[]'、404ではありません。
ページの終わり-'next_page_token'がありません。
誤ったトークン-400 sのコード:PAGINATION_CURSOR_INVALID'。
9) Webhooks: 信頼できる配達
イベント(HMAC)にサインインし、処理前に確認します。
成功した処理への応答は2xx(ベスト204)です。
レシーバの一時的な障害-5xx;送信者は(指数関数バックオフ、ジッタ)を繰り返します。
'event_id'による重複除外と結果の保存(idempotent consumer)。
無効なペイロード-400/422再試行なし。
10)プロトコル適合性(gRPC/GraphQL)
gRPC→HTTP:- 'INVALID_ARGUMENT'→400
- 'UNAUTHENTICATED'→401
- 'PERMISSION_DENIED'→403
- 'NOT_FOUND'→404
- 'EXALLED_EXISTS'→409
- 'FAILED_PRECONDITION'→412/422
- 'RESOURCE_EXHAUSTED'→429
- '中止'→409
- 'UNAVAILABLE'→503
- 'DEADLINE_EXCEEDED'→504
json
{
"data": { "createPayment": null },
"errors": [{
"message": "Forbidden",
"extensions": { "code": "FORBIDDEN", "status": 403, "trace_id": "..." },
"path": ["createPayment"]
}]
}
クリティカルエラーの場合は、200ではなく対応するHTTPコードを使用することをお勧めします。
11)タイトルと顧客のヒント
'Retry-After'-seconds/HTTP date (429/503/425/408)。
'Warning'-ソフト劣化または非推奨(「199-Feature X is depressed」)。
'Deprecation'、 'Sunset'、 'Link:<……>;rel=「deprecation」'-制御されたシャットダウンのために。
'Problem-Type'(カスタム)-クライアント上で高速なエラールーティング。
'X-Trace-Id'/'Correlation-Id'-ログ/トレースをリンクします。
12)メッセージセキュリティ
レスポンスボディで入力秘密(トークン/署名)を繰り返しないでください。
マスクPAN/PII ('1234')。
401/403の場合-どの属性が失敗したかを開示しないでください。
404のために、代わりに「リソースが存在しますが、あなたのものではありません」-ちょうど404。
13)エラーの観測可能性
メトリクス:- 'http_errors_total {status、 route、 tenant}'
- 'error_classes_total {code}' (bodyから'code'による)
- シェア429、 5xx;'p95'/'p99'誤った回答のレイテンシを別々に
- 'retry_after_seconds_bucket'-反復ヒントのヒストグラム
- 応答を'trace_id'、ストア'code'、 'type'、 'status'、 'route'、 'tenant'、 no PIIに関連付けます。
- RPS> Nでのスパイク'5xx_rate> X%';
- 重要なルートでの429の成長。
- 依存関係の'timeout/504';
- 頻繁に409/idempotency→レースの兆候。
14)例
14.1,422名(事業検証)
json
{
"type": "https://errors.example.com/payments/limit-exceeded",
"title": "Limit exceeded",
"status": 422,
"code": "PAYMENT_LIMIT_EXCEEDED",
"detail": "Daily withdrawal limit reached for KYC1.",
"hint": "Increase limits after KYC2 or try tomorrow.",
"trace_id": "01J5...XYZ"
}
14.2,409名(idempotency)
HTTP/1.1 409 Conflict
Idempotency-Replay: true
json
{
"type": "https://errors.example.com/idempotency/replay",
"title": "Duplicate request",
"status": 409,
"code": "IDEMPOTENT_REPLAY",
"detail": "A request with the same Idempotency-Key was already processed.",
"hint": "Reuse the same Idempotency-Key and GET the operation status."
}
14.3,429名(上限)
json
{
"type":"https://errors.example.com/rate/too-many-requests",
"title":"Too many requests",
"status":429,
"code":"RATE_LIMITED",
"detail":"Per-key rate limit exceeded.",
"hint":"Retry after the time specified in Retry-After header."
}
15) Antipatterns
200をボディエラーテキストで返します。
サービス間で異なるエラーフォーマットを混在させます。
'detail'でstack/SQL/テーブル名/内部URLを展開します。
安定した'code'/'type'の代わりに'message'を使用します。
予想されるビジネスエラーが発生したときに500を返します(たとえば「、残高が不十分です」)。
REST/GraphQL/gRPC間の整合性のない意味論。
16) iGaming/Financeの詳細
KYC/AML/制裁のクリアコード:'KYC_REQUIRED'、 'KYC_REVIEW'、 'AML_LOCK'、 'ANCTION_BLOCKED'。
管轄の制限:451リストなしで安全な言葉遣い。
通貨の書き込み操作:409/423競合とロックのために、やり直しウィンドウで'ヒント'。
プレーヤー制限不変量:責任ある支払い違反に422を使用します。
監査:変更できないソリューションログ(コード、時間、アクターtrace_id)。
17) Prod Readinessチェックリスト
- 単一のJSONエラースキーム、安定した'type'/'code'。
- HTTP ↔ gRPC/GraphQLマッピングは一貫しており、文書化されています。
- Retray semantics+'Retry-After';書くためのidempotency。
- PII/シークレットマスキング;資源を隠すために404。
- エラーとアラートメトリック;'trace_id'との相関。
- 非推奨ポリシー:'Deprecation'、 'Sunset'、 'Link'。
- テスト:negative/fuzz、 version conflict、 dependency drop、 double-submit。
- カスタマーガイド:バックオフサンプルと409/422/429/5xx処理。
18) TL;DR(ドクター)
'type'/'code'/'trace_id'で単一のJSONエラーフォーマットを標準化し、正しいHTTPコードを使用し、検証(400/422)、 (401/403/404 rights)、 conflicts/idempotency (409)、 limits (429)を区別します。'Retry-After'と'hint'をクリアし、機密データをマスクし、'trace_id'でエラーを記録し、5xx/429/p99でアラートをビルドします。