CLAUDE LABEN
FORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられていますFORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられています
記事一覧/API & SDK
API & SDK/2026-05-31上級

Claude 非同期パイプラインで「毒メッセージ」を隔離する — デッドレターキュー設計の実装メモ

1件の壊れた入力がバッチ全体を止める「毒メッセージ」問題を、Cloudflare Queues のデッドレターキューで隔離する設計と実装。Claude API 特有の失敗パターンの切り分けまで実体験ベースでまとめます。

Claude API115非同期処理4Cloudflare Queuesデッドレターキュー本番運用36

プレミアム記事

壁紙アプリの新作分を一括でタグ付けしようと、画像メタデータ 800 件を Claude にまとめて投げたことがあります。300 件ほど処理が進んだところでパイプラインが固まり、ログを追うと、たった 1 件の壊れた JSON がコンシューマを例外で落とし、その後ろの全件がリトライの渋滞に巻き込まれていました。原因の 1 件は、過去のエクスポート不具合で description フィールドに生のバイナリが混ざっていたものでした。

この「1 件の壊れた入力が、健全な残り全部を巻き添えにする」現象は、メッセージキューの世界で 毒メッセージ(poison message) と呼ばれています。同期的に for ループで API を叩いているうちは表面化しませんが、非同期キューに載せて本番運用を始めた瞬間、必ず一度はぶつかる落とし穴です。私が壁紙アプリのバックエンド処理と 4 サイトのコンテンツ生成パイプラインで実際に踏んだこの問題を、ここでは デッドレターキュー(DLQ) で隔離する設計として整理してみます。

毒メッセージがパイプライン全体を殺す仕組み

非同期パイプラインの基本は「キューにジョブを積み、コンシューマが 1 件ずつ取り出して Claude API を呼ぶ」という形です。健全に動いているうちは美しいのですが、コンシューマが処理に失敗したときの挙動が問題になります。

多くのキューは「失敗したメッセージは ack せず、一定時間後に再配信する」という at-least-once 配信を採ります。これは一時的なネットワーク断や 429(レート制限)には有効です。しかし、メッセージそのものが壊れていて 何度処理しても必ず失敗する 場合、同じメッセージが延々と再配信され続けます。

私の最初の実装では、この再配信が次の 3 つの形で残りの処理を巻き添えにしました。まず、壊れた 1 件がバッチの先頭に居座り、retryAll() を呼ぶ実装になっていたため、同じバッチに入っていた健全な 9 件も一緒に再送されました。次に、再送のたびに Claude API のトークンを消費するため、1 件の毒メッセージが静かに課金を膨らませました。最後に、リトライ回数の上限を設けていなかったため、毒メッセージがキューに永久に居座り、可視性タイムアウトの間スループットを食い続けました。

毒メッセージ対策の本質は、「直る失敗」と「直らない失敗」を切り分け、後者を健全なフローから物理的に追い出す ことです。

まず「直る失敗」と「直らない失敗」を切り分ける

すべての失敗を一律にリトライする実装は、毒メッセージを増幅させます。Claude API を呼ぶパイプラインでは、エラーを大きく 3 種類に分けて考えると整理できます。

一時的でリトライすべきもの(transient)は、429 レート制限、529 過負荷、500/503、ネットワークタイムアウトです。これらは時間を置けば直るので、指数バックオフでリトライする価値があります。

入力起因で何度やっても直らないもの(毒メッセージ)は、400 invalid_request(リクエスト本体が壊れている)、メッセージのデシリアライズ失敗、スキーマ検証で弾かれる構造化出力、max_tokens に対して入力が大きすぎてどうしても収まらないケースです。これらは即座に DLQ へ送るべきです。

判断が分かれるグレーゾーンもあります。stop_reasonmax_tokens で途中で切れた応答、refusal で拒否された応答などです。これらは「リトライしても結果が変わりにくいが、入力の前処理を変えれば直る可能性がある」ため、回数を絞ったリトライののち DLQ へ送り、人間または別ロジックで再処理する設計が合っています。

この切り分けを 1 つの関数に閉じ込めておくと、コンシューマ本体がすっきりします。

// classify.ts — 失敗を「リトライ可 / 毒メッセージ」に分類する
import Anthropic from "@anthropic-ai/sdk";
 
export type Verdict = "retry" | "poison";
 
export function classifyError(err: unknown): Verdict {
  // SDK が投げる APIError には status が乗る
  if (err instanceof Anthropic.APIError) {
    const s = err.status;
    if (s === 429 || s === 529 || s === 500 || s === 503) return "retry";
    if (s === 400 || s === 422) return "poison"; // 入力が壊れている
    if (s === 401 || s === 403) return "retry";  // 鍵やIP制限。設定直しで回復
  }
  // ネットワーク系(abort / ETIMEDOUT など)は一時障害扱い
  const name = (err as Error)?.name ?? "";
  if (name === "AbortError" || /timeout|ECONNRESET|ETIMEDOUT/i.test(String(err))) {
    return "retry";
  }
  // JSON.parse 失敗やスキーマ違反は毒メッセージ
  if (err instanceof SyntaxError) return "poison";
  // 分類不能は安全側(リトライ)に倒す。回数上限で最終的に DLQ へ落ちる
  return "retry";
}

ポイントは、分類不能なものを「とりあえず毒メッセージ」にしない ことです。未知のエラーはリトライ側に倒し、後述する max_retries の上限で自然に DLQ へ落とします。こうすると、こちらが想定していなかった一時障害を、誤って毒メッセージとして捨ててしまう事故を防げます。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
リトライで直る一時障害と、何度送っても失敗する毒メッセージを stop_reason とエラー型で機械的に切り分ける判定ロジック
Cloudflare Queues の max_retries と dead_letter_queue を使い、壊れた1件でバッチ全体を止めない隔離パイプラインの実装コード(Before/After 付き)
DLQ に溜まったメッセージを原因別に分類し、安全に再処理(リドライブ)するための運用設計と、再処理時に二重課金を防ぐ冪等キーの付け方
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

API & SDK2026-07-12
Claude API の 413 request too large を設計で避ける — 送信前サイズ見積もりと分割の実装
長文と画像と tool_result を1リクエストに詰めすぎると Claude API は 413 request too large で落ちます。32MB の壁・base64 の膨張・処理段階で起きる隠れた上限を実測し、送信前にサイズを見積もって安全に分割する設計をコード付きでまとめました。
API & SDK2026-07-07
Claude API が本番で突然 429 を返し始めたとき — レート制限の余白をヘッダから計測して枯渇前に絞る運用メモ
429 が出てから慌ててリトライを入れるのは後手です。Claude API のレスポンスヘッダには残量が毎回書かれています。余白を継続計測し、枯渇する前に自分から絞る運用メモを、実装フックと計測ログの読み方でまとめます。
API & SDK2026-07-01
Claude API のドキュメント抽出が「自信満々に間違える」とき — 沈黙する誤りを不変条件で捕まえる運用メモ
請求書や契約書の構造化抽出で一番怖いのは、クラッシュではなく「スキーマも通り信頼度も高いのに値だけ間違っている」沈黙の誤りです。不変条件・二段抽出・フィールド単位の誤り率で運用する実装メモを共有します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →