リゾルバーのエラーは HTTP 200 で返される
これは、エラー処理を書く前に知っておくべき最も重要な点です。 GraphQL over HTTP 仕様に従い、リゾルバーに到達したリクエストは、操作が失敗した場合でも HTTP 200 を返します。失敗はステータスコードではなく、レスポンスボディの中で報告されます。 そのため、次のチェックは機能しません:Content-Type に対する 415 など、一部のトランスポートエラーはボディが空であるため、パースする前にレスポンスが JSON であることを確認してください:
- 不正なリクエストはエラーステータスを返します。無効な JSON または
queryの欠落には HTTP 400、64 KB を超えるボディには 413、POST以外のメソッドには 405、サポートされていないContent-Typeには 415 が返されます。 - スキーマに対して無効なクエリは、リクエストで
Accept: application/graphql-response+jsonを送信した場合にのみ HTTP 400 を返します。これには、構文エラー、不明なフィールド、誤った引数の型、無効な列挙値、クエリの制限を超えるクエリが含まれます。Accept: application/jsonを送信した場合、またはAcceptヘッダーを送信しない場合、同じエラーは HTTP 200 を返します。いずれの場合も、ボディにはerrors配列が含まれ、dataは含まれません。
errors 配列付きの HTTP 200 を返します。
エラーの形式
すべてのリゾルバーエラーは、HTTP に相当する API ステータスをextensions に含んでいます:
message— 人が読める説明。リゾルバーのエラーメッセージからは API キーやその他の認証情報が削除されますが、誤った型の変数など、送信した値に関するエラーではその値が含まれる場合があります。ログに記録する前に、messageは機密情報を含む可能性があるものとして扱ってください。path— クエリ内のどのフィールドが失敗したか。1 回のリクエストに複数のフィールドがある場合、これでどのフィールドかを判別します。extensions.status— 同等の REST 呼び出しが返したであろう HTTP ステータス。これで分岐してください。extensions.code— 内部のエンドポイントが提供する場合の、Ayrshare の数値エラーコード。extensions.retryAfter— 再試行までの待機時間が利用可能な場合に、上流のクォータまたはレート制限による 429 に含まれます。リクエストごとのディスパッチ予算による 429 には含まれません。
extensions.code はエラーコードリファレンスと合わせて使用するか、explainError に渡してください。
部分的な成功
リクエストで複数のものを要求し、その一部だけが成功した場合、data と errors の両方が返されます:
history は成功しており、そのデータは使用できます。再試行が必要なのは analytics だけです。errors が存在するからといってレスポンス全体を破棄しないでください。すでに課金されたデータを捨てることになります。
複数のソーシャルネットワークへの投稿における部分的な成功
複数のソーシャルネットワークへの投稿は、一部で成功し、他で失敗することがあります。これは GraphQL のエラーとしては報告されません。操作自体は機能しており、要求どおりのことを実行したうえで、何が起こったかを伝えているためです。 結果は 3 つの結果を区別します:postIds— 公開されたソーシャルネットワークと、その投稿 URL。成功したもののみです。errors— 失敗したソーシャルネットワークと、その理由。blocked— 試行の前に停止されたソーシャルネットワーク。たとえば、決定的な失敗が繰り返された後にソーシャルネットワークごとのサーキットブレーカーによって停止された場合です。これらは、プロバイダーへの試行がエラーを返したものとは区別されます。
status は "error" になるため、何も公開されなかったことを示す信頼できるシグナルではありません。実際に何が公開されたかは postIds を確認してください。
再試行
GraphQL API が自動的に再試行することはありません。 リクエストが失敗した場合、あなたの代わりに暗黙的に再試行されたものは何もありません。 これは特にミューテーションで重要です。createPost は idempotencyKey を公開しています。最初の試行の前に一意のキーを生成し、再試行のたびに同じキーとまったく同じペイロードを再利用してください。確定済みのリクエストを再試行すると、書き込みを繰り返す代わりに元の結果が再生されます。あいまいなレスポンスを受け取った後に新しいキーに切り替えないでください。
boostFacebookPost と instagramBoostPost も idempotencyKey を受け取り、これは実際の費用を保護します。同じキーと同じ引数で再試行すると、2 つ目の広告を作成して支払う代わりに、idempotentReplayed: true が付いた元の結果が返されます。1 つのキーは両方の Meta プラットフォームにわたってアカウント全体をカバーするため、Facebook のブーストのキーを Instagram のブーストに再利用しないでください。
キーが拒否された場合、extensions.status でその理由がわかります。createPost は、最初の試行がまだ処理中の場合は 409 を返すので、待ってから同じキーで再試行してください。ペイロードが最初の試行と異なる場合は 400 を返します。ブーストのミューテーションは、どちらの場合も 409 を返し、キーがもう一方のプラットフォームのブーストに使用されていた場合も 409 を返します。
addComment など、その他の書き込みには冪等キーがありません。レスポンスが失われた場合は、再度試行しても安全かどうかを判断する前に、ソーシャルネットワークまたは API の状態を確認してください。
2 つの異なる制限がどちらも 429 を報告し、それぞれ異なる対処が必要です。ディスパッチ予算は、同じリクエスト内ですでに 5 回の API 呼び出しが開始された後にのみルートフィールドを拒否し、そのメッセージは Query exceeds the per-request dispatch budget で始まります。これらのフィールドを 5 つ以下のリクエストに分割してください。待つ必要はありません。それ以外の 429 はレート制限またはクォータです。extensions.retryAfter が存在する場合はその秒数だけ待ち、存在しない場合はバックオフしてから再試行し、失敗したフィールドのみを再試行してください。読み取りでの 5xx は再試行しても安全ですが、例外が 1 つあります。generatePost はクエリですが、再試行すると AI ジェネレーターが再び呼び出され、別の API 呼び出しとしてカウントされ、異なるテキストが返されます。冪等性のない書き込みでの 5xx の場合は、再試行する前にそれが反映されたかどうかを照合してください。
一般的なステータス
不明なフィールド、誤った引数の型、無効な列挙値など、実行前に GraphQL 自体が発生させるエラーには
extensions.status がありません。上述のとおり、Accept ヘッダーに応じて HTTP 400 または 200 を返します。これらはクエリ自体が誤っていることを意味し、API 呼び出しは行われず、課金もされません。