Claude Media
Bedrock content-typeエラーの原因と対処 — Claude Code

Bedrock content-typeエラーの原因と対処 — Claude Code

Amazon Bedrock経由のストリーミング応答でcontent-typeが一致しないエラーの原因と、ゲートウェイの状態別の対処、2つの環境変数の違いをまとめます。

「Bedrock streaming response has an unexpected content-type」というエラーが出たら、疑う先はゲートウェイです。Claude CodeとAmazon Bedrockの間のゲートウェイやプロキシが、ストリーミング応答のボディかヘッダーを書き換えています。Bedrockはストリーミング応答をバイナリのevent-stream形式で返します。中継がその形式を壊すと、Claude Codeは読めないボディをデコードせずに拒否します。

恒久対処はゲートウェイ側の設定変更です。ただしゲートウェイの状態によって、効く環境変数が変わります。

このエラーが意味すること

Amazon Bedrockは、ストリーミング応答をapplication/vnd.amazon.eventstreamというcontent-typeで返します。Claude Codeは、成功ステータスのストリーミング応答でこの値以外が届くと、デコードせずにリクエストを失敗させます。リトライもしません。

エラーメッセージには、実際に届いたcontent-typeの値が入ります。

Bedrock streaming response has content-type "text/event-stream"; expected "application/vnd.amazon.eventstream". A gateway or proxy between Claude Code and Bedrock is likely transforming the response body — Bedrock's binary event-stream format must be passed through unmodified. Set CLAUDE_CODE_DISABLE_BEDROCK_CONTENT_TYPE_GUARD=1 to suppress this check while the gateway is being fixed.

典型的な書き換えはtext/event-streamです。ストリームをサーバー送信イベント(SSE)として再送信する統合が、バイナリのevent-streamを別の形式に作り替えるとこの値になります。原因はClaude Code側にもBedrock側にもなく、その間に挟まった1台です。

まず切り分ける — 4つの手順

メッセージに出る値を起点にすれば、ゲートウェイ側の確認は短く済みます。

手順

ゲートウェイの確認順

  1. 1

    エラーに出たcontent-typeを読む

    引用符の中の値が、ゲートウェイの返しているヘッダーです。

  2. 2

    宛先のAPIを確かめる

    Claude Codeが使うのはInvoke API(InvokeModelWithResponseStream)です。Converse APIには対応していないので、Converse側の設定を触っても流れるエンドポイントは変わりません。

  3. 3

    ゲートウェイがボディとヘッダーを両方通しているか見る

    ヘッダーだけ書き換えているのか、ボディごと変換しているのかで、後の対処が分かれます。次の節の表で状態を当てはめます。

  4. 4

    心当たりのない中継を探す

    自前のゲートウェイを置いていなくても、TLS検査プロキシやセキュリティ製品が経路に入っていることがあります。その場合はClaude Codeプロキシ設定ガイドの経路確認も役に立ちます。

ゲートウェイの状態で結果が分かれる

同じ「ゲートウェイが応答をいじっている」状態でも、Claude Codeの反応は4通りに分かれます。

ゲートウェイの動作Claude Codeの反応気づく症状
Content-Typeを別の値に書き換えるClaude Codeの反応エラーで失敗する(v2.1.208以降)気づく症状content-typeを名指しするエラー
Content-Typeを落とす、または空にする。ボディは無加工Claude Codeの反応Bedrockのevent-streamとみなしてデコードする。ストリーミングは継続気づく症状なし(普通に動く)
Content-Typeを落とし、ボディもSSEに再送信するClaude Codeの反応デコードできず、毎ターン非ストリーミングの遅い経路に落ちる気づく症状エラーなし。応答が完成してから一度に出る遅さ
ストリームをSSEに変換し、Anthropic Messages APIも受け付けるClaude Codeの反応もはやBedrock APIではないので、接続方式そのものを変える気づく症状—

2行目は見落とされやすい点です。ヘッダーが欠けているだけで中身が無傷なら、エラーにはならず普通に動きます。エラーが出るのは、値が別の内容で埋まっているときだけです。

3行目は逆に、エラーが出ないぶん発見が遅れます。各応答は完成してから一度に表示されるため、ストリーミングで少しずつ出ていた応答が急に固まって見えるようになります。症状は「エラー」ではなく「遅さ」として現れます。

2つの環境変数は別のことをする

名前が似ているので、混同しやすい2つを並べます。

くらべる

GUARD と DEFAULT の違い

v2.1.208以降

CLAUDE_CODE_DISABLE_BEDROCK_CONTENT_TYPE_GUARD=1

content-typeが違うことを理由にした拒否をやめます。エラーは消えますが、書き換えられたヘッダーの下のバイナリボディは読めないため、該当リクエストは非ストリーミングの遅い経路にフォールバックします。この変数はゲートウェイを直すまでのつなぎです。

v2.1.239以降

CLAUDE_CODE_DISABLE_BEDROCK_CONTENT_TYPE_DEFAULT=1

ヘッダーが欠けている、または空の応答を、Bedrockのevent-streamとして扱うのをやめます。ヘッダーを落としたうえでボディをSSEにしているゲートウェイ向けで、本文をSSEとして読みます。

エラーが出ているなら関係するのはGUARDです。DEFAULTが関わるのは、エラーが出ないまま毎ターン遅くなっている場合です。

対処 — ゲートウェイ側の設定を直す

正しい対処は、InvokeModelWithResponseStreamのレスポンスボディとContent-Typeヘッダーの両方を、Bedrockが返したとおりに通すことです。SSEとして再送信する統合は、どちらかを壊しがちです。

直すまでの間にエラーだけ消したいときの書き方は次のとおりです。

export CLAUDE_CODE_DISABLE_BEDROCK_CONTENT_TYPE_GUARD=1

設定したあとは、エラーが消えたかどうかでなく、応答が少しずつ流れて表示されるかで確かめます。

ゲートウェイがAnthropic Messages APIも受け付けているなら、別の選択肢があります。SSEに変換するゲートウェイは、もうBedrock APIを提供していません。その場合はCLAUDE_CODE_USE_BEDROCKではなく、ANTHROPIC_BASE_URLでLLMゲートウェイとして接続します。ゲートウェイ方式の比較はLLMゲートウェイ比較にあります。

バージョンで見え方が変わる

v2.1.208より前は、同じ誤設定がAPI Error: Truncated event message receivedとして現れました。応答全体をバッファリングした後に出るため、原因が見えにくいエラーでした。v2.1.208以降は、成功ステータスのストリーミング応答で、受信したcontent-typeを名指しして失敗します。 GUARDの環境変数もv2.1.208以降が前提で、DEFAULTはv2.1.239以降です。claude --versionでバージョンを確かめ、古ければ先に更新します。

ゲートウェイを前提にした接続の組み方

Bedrockの前に社内ゲートウェイを置く構成は、接続先の指定が2通りあります。ゲートウェイが返す応答の形で、どちらを選ぶかが決まります。

Bedrock APIをそのまま中継するゲートウェイなら、CLAUDE_CODE_USE_BEDROCKを保ったまま、エンドポイントを差し替えます。差し替えにはANTHROPIC_BEDROCK_BASE_URLを使います。LLMゲートウェイ経由にするときの変数です。

認証をゲートウェイが肩代わりするなら、CLAUDE_CODE_SKIP_BEDROCK_AUTH=1でクライアント側のAWS認証を省けます。LLMゲートウェイを使う場合が想定された変数です。

この構成でゲートウェイが返す応答は、Bedrockのevent-streamとして無加工でなければなりません。

Bedrockの別系統であるMantleエンドポイントは、Bedrock APIの中継とは別の変数で指定します。接続先はANTHROPIC_BEDROCK_MANTLE_BASE_URL、認証の省略はCLAUDE_CODE_SKIP_MANTLE_AUTHです。

似た配信エラーとの違い

Bedrock経由でゲートウェイを通すと、content-type以外にも症状の近いエラーが出ます。

症状原因の層対処
content-type不一致原因の層ゲートウェイが応答形式を書き換えている対処ゲートウェイ設定を直す
Streaming response ended before any complete data was received原因の層ストリーミングの応答が、使えるデータを返さずに終わった対処ゲートウェイでボディとヘッダーを無加工にする
API returned an empty or malformed response原因の層非ストリーミングの再試行が、API応答ではない本文を受け取った対処Response:の内容から、どの系が返したかを見る
ストリームが停止して進まない原因の層接続は保たれているがデータが来ない対処CLAUDE_ENABLE_BYTE_WATCHDOG_BEDROCK=1でBedrock向けのバイト単位監視を有効化(ANTHROPIC_BEDROCK_BASE_URL経由のゲートウェイは対象外)

2行目は、Claude Codeが非ストリーミングで1回やり直したうえで、対話セッションでのみ、1セッションにつき1度だけ警告を出す仕組みです。つまりリクエストが2回送られます。ゲートウェイがボディを飲み込んでいるときの症状なので、content-typeエラーと原因が近いところにあります。

ゲートウェイの非ストリーミング経路だけが壊れている場合は、CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK=1でこのフォールバックを止められます。ストリーミングのエンドポイント自体が404を返すときは例外です。

3行目は、v2.1.271より前だと、有効なAPIメッセージがtext/plainのような非JSONのcontent-typeで届いたときにも出ました。非ストリーミングの応答にこの型を使うLLMゲートウェイがあります。

停止の件は別の仕組みです。Claude Codeには、静かになったストリームを打ち切る4種類のタイマーがあります。応答ヘッダーを待つ最初のバイトの期限、イベント単位の監視、バイト単位の監視、本文のアイドルタイムアウトです。Bedrockでは、バイト単位の監視と最初のバイトの期限が既定で動いていません。CLAUDE_ENABLE_BYTE_WATCHDOG_BEDROCK=1でこの2つが有効になり、本文のアイドルタイムアウト(5分)はバイト単位の監視に置き換わります。

ただし、ANTHROPIC_BEDROCK_BASE_URLのようなプロバイダーのベースURLで届くゲートウェイには、バイト単位の監視が掛かりません。

有効にしたあとは、CLAUDE_STREAM_IDLE_TIMEOUT_MSが、Bedrockのストリームを無音のまま許す長さを決めます。明示的に設定する場合の下限は300000(5分)で、これより小さい値は黙って切り上げられます。バイト単位の監視は、この値を30分で頭打ちにします。v2.1.210以降はCLAUDE_BYTE_STREAM_IDLE_TIMEOUT_MSもあり、バイト単位の監視ではこちらが優先されます。デバッグログを出すと、各ストリームにwire-heartbeat: _chunkTimes absentで始まるメッセージが記録されます。Bedrockのストリームで停止が疑わしいときは、この行が出ているかを見れば、監視が有効になったかを確かめられます。デバッグログはclaude --debugで出せます。

再試行されるエラーと、されないエラー

Claude Codeは一時的な障害を自動で再試行しますが、すべてを再送するわけではありません。経路上の機器が原因になる失敗でも、扱いは分かれます。content-typeエラーは再送されません。

TLS証明書の検証失敗は、その対比になります。v2.1.199以降は、TLS証明書の失敗を最初の試行で報告します。v2.1.198までは再試行の枠を使い切ってから表示されました。ただし、ハンドシェイクのタイムアウトのような一時的な不調は、今も再試行されます。TLS検査プロキシが経路に入っているなら、症状はcontent-typeではなく、SSL certificate verification failedとして現れます。対処はNODE_EXTRA_CA_CERTSにそのCAのバンドルを指定することです。

企業のTLS検査プロキシは、ルート証明書がOSの信頼ストアに入っていて、ランタイムがそれを読めれば、追加設定なしで動きます。

ゲートウェイが応答を完成まで保留する構成では、API_TIMEOUT_MSを延ばすと再試行の待ち時間が長くなります。BedrockではCLAUDE_STREAM_FIRST_BYTE_TIMEOUT_MS(v2.1.242以降)も延ばします。

よくあるつまずき

  • 環境変数を設定しても遅いままなら、エラーを隠しただけで、ボディ変換が残っていないかを疑います
  • 設定を直した後の確認は、非ストリーミングへのフォールバックでもエラーは出ないため、応答が少しずつ流れて表示されるかで行います

まとめ

症状がエラーならGUARD、エラーなしで毎ターン遅いならDEFAULT、ゲートウェイがSSE変換でMessages APIも受けるならANTHROPIC_BASE_URLが当たります。どれも恒久策ではなく、直す先はゲートウェイです。

この記事を共有:XはてブLinkedIn