概要
ドメイン層の検証エラー(入力起因 = クライアント起因)が一部のハンドラで 500 Internal Server Error に落ちている。エラーの責務に応じて 400 Bad Request を返すよう、全エンドポイントで一貫した方針に統一したい。
これは #13(残高不足 → 400)と同根の「クライアント起因エラーを 400 に寄せる」設計判断の話。#13 は残高不足に限定したスコープのため、こちらで横断的な方針を扱う。
現状の不整合
ドメイン検証エラーの扱いがエンドポイントごとにバラバラ:
| 箇所 |
ドメイン検証エラーの扱い |
user.go GET (ErrInvalidUserID) |
400(sentinel + errors.Is でマッピング済み)✅ |
user.go RegisterUser |
ErrUserAlreadyExists のみ 409、その他ドメイン検証は 500 ❌ |
purchase.go CreatePurchase |
NewPurchaseItem(itemID/quantity <= 0)・NewPurchase 等の検証失敗が 500 ❌ |
user.go の ErrInvalidUserID だけが正しく 400 に寄っており、他は素の errors.New(...) を返すため sentinel 判定ができず 500 に落ちる。
何が問題か
- 同じ「不正入力」でもエンドポイントによって 400 だったり 500 だったりして、フロントの扱いが一貫しない
- クライアント起因のエラーで 500 が返ると、リトライ・障害アラートを誘発する
- 既に
ErrInvalidUserID という良いお手本があるのに、他が踏襲できていない
提案する方針
ErrInvalidUserID のパターンを横展開する:
- ドメイン検証エラーを sentinel error として定義(または検証エラーをまとめる
ErrInvalidInput 的なマーカーを導入)
- usecase 層で sentinel をラップして伝播
- ハンドラで
errors.Is(...) → 400 にマッピング
NewPurchaseItem / Set* など多数の検証関数があるため、個別 sentinel 乱立を避けて「ドメイン検証エラー」を表す共通マーカー error を1つ用意する案も検討したい(要相談)。
関連ファイル
app/domain/object/purchase/purchase.go(NewPurchaseItem, Set* 検証群)
app/domain/object/user/(SetUserID 等)
app/usecase/purchase/create_purchase.go
app/ui/api/purchase/purchase.go
app/ui/api/user/user.go
備考
これは既存慣習であり、特定 PR が壊したものではない。横断的な設計判断を要するため、実装前に共通マーカー方式か個別 sentinel 方式かを決めたい。
概要
ドメイン層の検証エラー(入力起因 = クライアント起因)が一部のハンドラで
500 Internal Server Errorに落ちている。エラーの責務に応じて400 Bad Requestを返すよう、全エンドポイントで一貫した方針に統一したい。これは #13(残高不足 → 400)と同根の「クライアント起因エラーを 400 に寄せる」設計判断の話。#13 は残高不足に限定したスコープのため、こちらで横断的な方針を扱う。
現状の不整合
ドメイン検証エラーの扱いがエンドポイントごとにバラバラ:
user.goGET (ErrInvalidUserID)400(sentinel +errors.Isでマッピング済み)✅user.goRegisterUserErrUserAlreadyExistsのみ 409、その他ドメイン検証は500❌purchase.goCreatePurchaseNewPurchaseItem(itemID/quantity <= 0)・NewPurchase等の検証失敗が500❌user.goのErrInvalidUserIDだけが正しく 400 に寄っており、他は素のerrors.New(...)を返すため sentinel 判定ができず 500 に落ちる。何が問題か
ErrInvalidUserIDという良いお手本があるのに、他が踏襲できていない提案する方針
ErrInvalidUserIDのパターンを横展開する:ErrInvalidInput的なマーカーを導入)errors.Is(...)→400にマッピングNewPurchaseItem/Set*など多数の検証関数があるため、個別 sentinel 乱立を避けて「ドメイン検証エラー」を表す共通マーカー error を1つ用意する案も検討したい(要相談)。関連ファイル
app/domain/object/purchase/purchase.go(NewPurchaseItem,Set*検証群)app/domain/object/user/(SetUserID等)app/usecase/purchase/create_purchase.goapp/ui/api/purchase/purchase.goapp/ui/api/user/user.go備考
これは既存慣習であり、特定 PR が壊したものではない。横断的な設計判断を要するため、実装前に共通マーカー方式か個別 sentinel 方式かを決めたい。