SQS から10件のメッセージを受け取る Lambda 関数で、1件だけ処理に失敗した。すると、成功していたはずの9件まで、しばらくしてもう一度処理されてしまう。SQS と Lambda を組み合わせると、一度はぶつかる問題です。

結論:イベントソースマッピングで ReportBatchItemFailures を有効にします。関数が失敗したメッセージの ID だけを batchItemFailures で返せば、失敗した分だけが再びキューに表示されます。

この記事では、AWS Lambda のデベロッパーガイドを根拠に、仕組みと書き方を整理します。返すデータの形は、手元でハンドラーを動かした出力でも確かめます。なお筆者は AWS SAA を取得(その後失効)していますが、DVA は保有していません。この記事は受験の体験談ではなく、公式ドキュメントにもとづく解説です。

この記事で分かること:

  • ReportBatchItemFailures が無いと、なぜ成功したメッセージまで再処理されるのか
  • 有効にする方法と、関数が返す JSON の形(実行結果つき)
  • 成功・失敗と判定される条件、FIFO キューでの注意点
  • AWS DVA での問われ方

※記事の内容は、2026年10月13日に AWS 公式ドキュメント(日本語版・英語版)と AWS 認定の公式ページで確かめたものです。AWS のドキュメントや試験は更新されることがあるため、最新の内容は公式サイトで確認してください。



結論:既定の動きと部分的なバッチレスポンスの違い

既定では1件の失敗でバッチ全体がキューに戻り、ReportBatchItemFailures を有効にすると失敗した分だけが戻ります。AWS Lambda のデベロッパーガイドによると、関数がバッチの処理中にエラーになると、そのバッチ内のすべてのメッセージが再びキューに表示されます。Lambda が正常に処理したメッセージも含まれます。

項目 既定の動き 部分的なバッチレスポンス(ReportBatchItemFailures)
1件が失敗したとき バッチ内の全メッセージが再びキューに表示される 関数が報告した失敗メッセージだけが再び表示される
成功したメッセージ 再処理されることがある 再処理されない
関数の返り値 決まりはない batchItemFailures に失敗した ID を入れて返す
失敗したときのポーリング Lambda が同時実行数を減らしてバックオフする 関数の呼び出しが失敗してもポーリングをスケールダウンしない

横にスクロールできます

再びキューに表示されるのは、キューの可視性タイムアウトが過ぎたあとです。つまり既定の動きのままだと、1件の失敗のたびに、成功していたメッセージまで同じ処理をもう一度受けることになります。

後輩
重複して処理されても、結果が同じなら困らなくないですか?
先輩
メールを送る、在庫を引き当てる、課金する、みたいな処理だと困るよね。同じ注文の確認メールが2通届いたら事故だ。だから「成功した分は戻さない」仕組みが用意されているんだよ。

※この章の内容は AWS Lambda デベロッパーガイド「Lambda での SQS イベントソースのエラーの処理」「Amazon SQS イベントソースマッピングの作成と管理」より


有効にする方法と返すJSON

やることは2つです。イベントソースマッピングの FunctionResponseTypes に ReportBatchItemFailures を指定します。そして、関数が失敗したメッセージの ID を返すようにします。

1. イベントソースマッピングで有効にする

デベロッパーガイドには、AWS CLI で次のように有効にする例が載っています。イベントソースマッピングの UUID は list-event-source-mappings コマンドで調べます。

aws lambda update-event-source-mapping \
  --uuid "a1b2c3d4-5678-90ab-cdef-11111EXAMPLE" \
  --function-response-types "ReportBatchItemFailures"

2. 失敗したメッセージの ID を返す

関数は、すべての例外をキャッチし、失敗したメッセージを batchItemFailures というリストで返します。リストの各要素は、itemIdentifier というキーにメッセージ ID を持ちます。

デベロッパーガイドの例では、id1〜id5 の5件のうち id2 と id4 が失敗した場合、関数は次のレスポンスを返します。

{
  "batchItemFailures": [
    { "itemIdentifier": "id2" },
    { "itemIdentifier": "id4" }
  ]
}

このレスポンスを受け取った Lambda は、id2 と id4 だけを再びキューに表示させます。id1・id3・id5 は再処理されません。

※この章の内容は AWS Lambda デベロッパーガイド「Lambda での SQS イベントソースのエラーの処理」より


実行して返り値を確かめる

メッセージごとに try で囲み、失敗した ID だけを集めて返すのが基本の書き方です。次の Python のハンドラーで、返り値の形を確かめました。

import json

def process(body):
    order = json.loads(body)          # 壊れたJSONならここで例外
    if order["qty"] <= 0:
        raise ValueError("qty must be positive")

def lambda_handler(event, context):
    failures = []
    for record in event["Records"]:
        try:
            process(record["body"])
            print(f"OK   {record['messageId']}")
        except Exception as e:
            print(f"FAIL {record['messageId']}: {type(e).__name__}")
            failures.append({"itemIdentifier": record["messageId"]})
    return {"batchItemFailures": failures}

# SQS イベントの形を手で組み立てて、ローカルで関数を呼ぶ(AWS 上の実行ではない)
bodies = ['{"qty": 1}', '{"qty": 0}', '{"qty": 3}', 'not-json', '{"qty": 2}']
event = {"Records": [{"messageId": f"id{i+1}", "body": b} for i, b in enumerate(bodies)]}
print(json.dumps(lambda_handler(event, None), indent=2))
Python のハンドラーに5件のメッセージを渡した実行結果。id1・id3・id5 は OK、id2 は ValueError、id4 は JSONDecodeError で FAIL となり、最後に batchItemFailures として id2 と id4 の itemIdentifier を含む JSON が出力されている
SQS イベントと同じ形のデータを手で組み立て、ハンドラーをローカルの Python で呼び出した結果(筆者の手元で実行・2026年10月13日)。AWS 上での実行ではない。失敗した id2 と id4 だけが batchItemFailures に入っている。

出力を読むと、次のことが分かります。

  • id2 は数量が0なので ValueError、id4 は本文が JSON ではないので JSONDecodeError で失敗しています。
  • 失敗しても例外は関数の外へ出ていません。メッセージごとに except で受け止め、ID をリストに足しています。
  • 返り値は、デベロッパーガイドの例と同じ batchItemFailures と itemIdentifier の形です。

ここで大事なのは、例外を関数の外へ投げないことです。次の章で見るとおり、関数が例外をスローすると、バッチ全体が失敗として扱われます。

なお、実際の SQS のイベントには messageId と body のほかにも多くの項目があります。この例では、返り値の形を確かめるために必要な2つだけを使っています。

後輩
AWS 上で動かしていないのに、確かめたことになるんですか?
先輩
ここで確かめたのは「自分のハンドラーが、ドキュメントどおりの形を返すか」だね。実際に失敗分だけがキューに戻るかは、AWS 上で SQS のメトリクスを見て確かめる必要がある。見るべきメトリクスは次の章で紹介するよ。

成功と失敗の条件

空のリストを返せばバッチ全体が成功、形が壊れたレスポンスを返すとバッチ全体が失敗として扱われます。デベロッパーガイドは、Lambda がバッチをどう扱うかを次のように定めています。

Lambda の扱い 関数がこれを返したとき
バッチ全体を成功として扱う 空の batchItemFailures リスト/null の batchItemFailures リスト/空の EventResponse/null の EventResponse
バッチ全体を失敗として扱う 無効な JSON レスポンス/空文字列の itemIdentifier/null の itemIdentifier/キー名が間違っている itemIdentifier/存在しないメッセージ ID を持つ itemIdentifier

横にスクロールできます

加えて、関数が例外をスローした場合も、バッチ全体が完全な失敗とみなされます。

落とし穴になりやすいのは次の2つです。

  • キー名を間違える:itemIdentifier を itemId などと書くと、失敗分だけでなくバッチ全体が失敗になります。
  • 全件成功を表すつもりで例外を握りつぶす:失敗したメッセージをリストに入れ忘れると、空のリスト=全件成功として扱われ、失敗したメッセージはキューから消えます。

ちゃんと動いているかは、Amazon SQS の CloudWatch メトリクスで確かめられます。デベロッパーガイドは、NumberOfMessagesDeleted が0に落ちたら、関数のレスポンスが失敗したメッセージを正しく返していない兆候だとしています。ApproximateAgeOfOldestMessage の急な増加も、同じ問題のサインになりうるとしています。

※この章の内容は AWS Lambda デベロッパーガイド「Lambda での SQS イベントソースのエラーの処理」より


設定するときの注意点

FIFO キューの動き、可視性タイムアウト、デッドレターキューの3つは、部分的なバッチレスポンスとあわせて押さえておきます。

FIFO キューでは最初の失敗で止まる

FIFO キューで使う場合、関数は最初の失敗のあとでメッセージの処理を止め、失敗したメッセージと未処理のメッセージをすべて batchItemFailures で返します。キュー内のメッセージの順序を保つためです。標準キューのように「失敗した1件だけを返し、後ろのメッセージは処理を続ける」書き方をしないよう注意してください。

可視性タイムアウトは関数のタイムアウトの6倍以上

デベロッパーガイドは、ソースキューの可視性タイムアウトを、関数に設定したタイムアウトの少なくとも6倍にするよう勧めています。関数のタイムアウトがキューの可視性タイムアウトを超えていると、イベントソースマッピングの作成・更新のときにエラーになります。

何度も失敗するメッセージはデッドレターキューへ

1つのメッセージの処理に何度も失敗する場合、Amazon SQS はそのメッセージをデッドレターキューに送れます。デベロッパーガイドは、ソースキューの再処理ポリシーで maxReceiveCount を少なくとも5に設定するよう勧めています。

自分で書かずに済ませる方法もある

Powertools for AWS Lambda のバッチプロセッサユーティリティを使うと、部分的なバッチレスポンスのロジックを自動で処理できます。デベロッパーガイドによると、Python・Java・TypeScript・.NET で使えます。

バイセクトは SQS の機能ではない

BisectBatchOnFunctionError は、失敗したバッチを2つの小さなバッチに分けて不良レコードを切り分ける設定です。デベロッパーガイドでは Kinesis などのストリームのイベントソースのエラー処理として説明されており、Amazon SQS のイベントソースマッピングのパラメータ一覧には含まれていません。

設定 対象 何をするか
ReportBatchItemFailures SQS 関数が報告した失敗分だけを再処理させる
BisectBatchOnFunctionError Kinesis などのストリーム 失敗したバッチを2つに分けて不良レコードを切り分ける

横にスクロールできます

※この章の内容は AWS Lambda デベロッパーガイド「Lambda での SQS イベントソースのエラーの処理」「Amazon SQS イベントソースマッピングの作成と管理」「Amazon SQS イベントソースマッピング用の Lambda パラメータ」「Lambda で Kinesis Data Streams イベントソースの破棄されたバッチレコードを保持する」より


AWS DVAでの問われ方

Lambda のエラー処理は、AWS DVA(DVA-C02)の試験ガイドにある論点です。DVA-C02 の試験ガイドでは、コンテンツ分野1「AWS のサービスによる開発」(採点対象コンテンツの32%)に、「コード (Lambda 送信先、デッドレターキューなど) を使用したイベントライフサイクルとエラーを処理する」「メッセージングサービスを使用するためのコードを記述する」といったスキルが載っています。

問題の形としては、次のようなものが考えられます。

  • 1件の失敗で成功分まで再処理される。失敗した分だけを再試行させる方法は?(ReportBatchItemFailures)
  • 「Kinesis と同じようにバイセクトを有効にする」は SQS で使えるか?(使えない)
  • 「バッチサイズを1にする」は要件を満たすか?(満たすが、処理効率が落ちる)
  • 何度も失敗するメッセージを隔離するには?(デッドレターキュー)

同じ論点を試験の形式で解きたい方は、筆者が運営するエンジニア資格合格ラボ(DVA-C02 対応)の ReportBatchItemFailures を問う無料問題 をどうぞ。ラボの問題は AI で作成し、検証したもので、有資格者の監修は入っていません。この1問を解けば合格できる、というものではありません。

受験の時期に注意

AWS 認定の公式ページによると、DVA は試験の更新中です。更新版の受験登録は2026年10月27日から始まり、現在の試験(DVA-C02)の最終受験日は2026年12月1日です。これから受ける方は、受ける試験の版と試験ガイドを先に確かめてください。

項目 AWS DVA(DVA-C02)
試験時間 130分
問題数 65問(うち採点対象外が15問)
合格スコア 720(100〜1,000の換算スコア)
受験料 150 USD

横にスクロールできます

AWS 資格をどの順番で取るかは AWS 認定資格のロードマップ、SAA の勉強の進め方は AWS SAA の勉強法 にまとめています。IAM の権限の決まり方は SCP と権限境界の違い で扱っています。DVA の勉強の進め方と、どちらの版を受けるかは AWS DVA 勉強法|C02とC03どちらを受ける? を参考にしてください。

※この章の試験情報は AWS 認定の公式ページ「AWS Certified Developer - Associate」と「試験ガイド (DVA-C02)」より


よくある質問(FAQ)

ReportBatchItemFailures を使わないと、何が起きますか?

A. バッチの処理中にエラーが起きると、既定ではそのバッチ内のすべてのメッセージが再びキューに表示されます。Lambda が正常に処理したメッセージも含まれるので、同じメッセージを複数回処理することになる場合があります。ReportBatchItemFailures を有効にすると、関数が報告した失敗メッセージだけを再び表示させられます。

関数は何を返せばいいですか?

A. 失敗したメッセージの ID を batchItemFailures というリストに入れて返します。リストの各要素は itemIdentifier というキーにメッセージ ID を持ちます。たとえば id2 と id4 が失敗したら、{"batchItemFailures": [{"itemIdentifier": "id2"}, {"itemIdentifier": "id4"}]} を返します。全件成功したときは、空のリストを返せばバッチ全体が成功として扱われます。

関数の中で例外を投げるとどうなりますか?

A. バッチ全体が完全な失敗とみなされます。AWS Lambda のデベロッパーガイドは、部分的なバッチレスポンスを使う場合、関数が例外をスローするとバッチ全体が完全な失敗とみなされると注意しています。メッセージごとに例外をキャッチし、失敗した ID をリストに集めて返す書き方にします。

FIFO キューでも使えますか?

A. 使えますが、動きが違います。FIFO キューで使う場合、関数は最初の失敗のあとでメッセージの処理を止め、失敗したメッセージと未処理のメッセージをすべて batchItemFailures で返します。キュー内のメッセージの順序を保つためです。

バッチのバイセクト(BisectBatchOnFunctionError)とは何が違いますか?

A. 対象のイベントソースが違います。BisectBatchOnFunctionError は Kinesis などのストリームのイベントソースマッピングで、失敗したバッチを2つに分けて不良レコードを切り分ける設定です。Amazon SQS のイベントソースマッピングのパラメータ一覧には含まれていません。SQS で失敗したメッセージだけを再処理させたいときは ReportBatchItemFailures を使います。

まとめ:ReportBatchItemFailures の使い方

  • 既定では1件の失敗でバッチ全体がキューに戻る。 成功したメッセージも再処理されることがある。
  • FunctionResponseTypes に ReportBatchItemFailures を指定する。 関数は失敗したメッセージの ID を batchItemFailures で返す。
  • 例外を関数の外へ投げない。 投げるとバッチ全体が失敗。キー名の間違い・存在しない ID も全体の失敗になる。
  • FIFO は最初の失敗で止まる。 失敗分と未処理分をすべて返す。
  • バイセクトはストリーム向けの設定。 SQS では ReportBatchItemFailures を使う。

出典

(いずれも2026年10月13日に確認)


免責:本記事は、2026年10月13日時点で AWS が公開しているドキュメントと試験情報、および筆者の手元でコードを実行した結果にもとづく情報提供です。記事中のハンドラーの実行は、AWS 上ではなくローカル環境で行ったものです。AWS のサービス仕様・試験内容・受験料は改定されることがあります。実装や受験の前に、必ず AWS の公式サイトで最新の情報を確認してください。本記事は合格や特定の成果を保証するものではありません。「AWS」および関連する名称は Amazon Web Services, Inc. またはその関連会社の商標です。