はじめに
こんにちは、nobushiueshiです。
REST APIを自作したことがある方なら、一度はこんな悩みを抱えたことがあるのではないでしょうか。
「エラーが起きたとき、レスポンスのJSON、どんな形式で返せばいいんだろう?」
たとえば、こんなふうに悩みます。
// これでいいの?
{ "error": "Not Found" }
// それともこっち?
{ "message": "リソースが見つかりません", "code": 404 }
// いや、もっと詳細にすべき?
{ "status": 404, "detail": "指定されたユーザーは存在しません" }
チームや個人プロジェクトによってバラバラになりがちなこの問題、実は RFCで標準が定められている ことを最近知りました。今回はそれを調べてみたので、まとめて紹介します。
RFC 9457 とは?
RFC 9457「Problem Details for HTTP APIs」 というドキュメントがあります。
これはHTTP APIがエラーを返すときの、JSONレスポンスの標準形式を定めたものです。以前は RFC 7807 として定義されていましたが、2023年に RFC 9457 として改訂・更新されています。
Content-Type は以下を使います。
application/problem+json
これ自体はまだ広く普及しているとは言いがたいですが、「標準仕様がある」という事実を知っているだけでも、API設計の議論がしやすくなります。
フィールドの定義
RFC 9457 では、以下のフィールドが定義されています。
| フィールド | 必須 | 説明 |
|---|---|---|
type | 任意 | エラーの種類を示すURI。ドキュメントへのリンクにもできる |
title | 任意 | エラーの短い人間向けの説明(英語が想定) |
status | 任意 | HTTPステータスコード(数値) |
detail | 任意 | エラーの詳細説明。人間向けのメッセージ |
instance | 任意 | エラーが発生した具体的なリソースのURI |
すべて任意ですが、type と detail あたりは入れておくと親切です。
また、これらに加えて独自のフィールドを自由に追加できるのも大きなポイントです。
サンプル:よくあるエラーケース
404 Not Found
HTTP/1.1 404 Not Found
Content-Type: application/problem+json
{
"type": "https://example.com/errors/user-not-found",
"title": "User Not Found",
"status": 404,
"detail": "指定されたID '42' のユーザーは存在しません。",
"instance": "/users/42"
}
400 Bad Request(バリデーションエラー)
バリデーションエラーのように複数のエラーをまとめて返したい場合は、独自フィールドを追加して対応できます。
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
{
"type": "https://example.com/errors/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "リクエストのパラメータに不正な値が含まれています。",
"instance": "/users",
"errors": [
{
"field": "email",
"message": "メールアドレスの形式が正しくありません。"
},
{
"field": "age",
"message": "年齢は0以上の整数である必要があります。"
}
]
}
401 Unauthorized
HTTP/1.1 401 Unauthorized
Content-Type: application/problem+json
{
"type": "https://example.com/errors/unauthorized",
"title": "Unauthorized",
"status": 401,
"detail": "このリソースへのアクセスには認証が必要です。",
"instance": "/admin/settings"
}
500 Internal Server Error
HTTP/1.1 500 Internal Server Error
Content-Type: application/problem+json
{
"type": "https://example.com/errors/internal-server-error",
"title": "Internal Server Error",
"status": 500,
"detail": "サーバー内部でエラーが発生しました。時間をおいて再度お試しください。"
}
ポイントまとめ
typeには エラーの種類を一意に識別するURI を入れる(実際にアクセスできるドキュメントURLにするのが理想)detailは ユーザーや開発者が原因を理解できる文章 にするinstanceは どのリソースでエラーが起きたか を示すために便利- 独自フィールド(
errorsなど)を追加して柔軟に拡張できる - Content-Type は
application/problem+jsonを使う
感想
正直、今まで「エラーのフォーマットなんて自分で決めればいいか」と思っていましたが、標準仕様があると知ってからは意識が変わりました。
特にチーム開発や、外部に公開するAPIを作る場合は、こういった標準に則っておくと「なぜこの形式なの?」という議論が不要になってスムーズです。個人開発でも、最初から標準形式に慣れておくと後々ラクになりますよ。
REST APIを作る機会がある方は、ぜひ RFC 9457 を意識してみてください!

コメント