GraphQL エラーハンドリング戦略
GraphQLのResponse には Payload と Errors がある。このうち Errors の使い方について説明する。
Backendが返す Errors の 型は以下のようになる。
json
{
"errors": [
{
"message": "エラーメッセージ",
"extensions": {
"code": "ERROR_CODE",
"notifyMessage": "ユーザー向けメッセージ"
}
}
]
}以下、 code と notifyMessage について説明する
エラーコード(code)について
| code | 中身 |
|---|---|
| UNAUTHENTICATED | 認証されていない |
| FORBIDDEN | アクセス権がない |
| BAD_USER_INPUT | ユーザー入力が無効 |
| INTERNAL_SERVER_ERROR | サーバー内部エラー |
エラーメッセージ(notifyMessage)について
エラーメッセージは基本的に Backend で定義します。どうしてもフロントエンド側でハンドリングしたい場合は、Payload型に含めてください。
Backend
こんな感じで渡します。
go
if ent.IsConstraintError(err) {
return nil, NewBadUserInputError(err, NewErrorOptions("ユーザー名が既に使用されています"))
}Frontend
基本的にはなにもしなくてOKです。 ただし、mutation でエラーが発生しても、ユーザーにエラーを通知したくないタイミングがあると思います。 その場合は、以下のように対応してください。
Javascript
contextでpreventErrorNotifyを渡してください。
javascript
const [updateScenarioMutation] = useMutation(UpdateScenarioDocument, {
context: {
preventErrorNotify: true,
},
});Dart
mutation に引数preventErrorNotifyを渡せるようにしたのでそれを使ってください。
背景
現状、プロダクトでは主にエラーハンドリング戦略として「パターン2」を採用しています。ValidationエラーはUXの観点から基本的にフロントエンドでやることが望ましいので、GraphQLで明示的に含める必要がなく、この戦略が効率的です。
エラーハンドリングのパターン
パターン1: スキーマにエラーを定義
この方法では、すべてのエラーコードがスキーマに定義され、エラーメッセージはフロントエンドで管理されます。
パターン2: GraphQLエラーメッセージを併用
スキーマにエラーは定義されず、バリデーションエラーはGraphQLのエラーメッセージとして返されます。
戦略
デフォルト: パターン2
フロントエンドでは、このエラーメッセージをそのままユーザーに通知します。
特定のケース: パターン1の併用
フロントエンドでのエラーハンドリングが必要な場合、パターン1を併用します。
- この時、スキーマの変更が必要なので、Backendチームとコミュニケーションを行いながら行います。
考慮すべきポイント
- 型安全性: パターン1を併用することで、フロントエンドで型安全にエラーを扱うことが可能です。
- メンテナンス性: パターン2をデフォルトとすることで、スキーマの肥大化を防ぎます。
- ユーザーエクスペリエンス: パターン2で渡されたメッセージをそのままユーザーに通知することで、エラーハンドリングのコストを削減します。