トラブルシューティング · コンテキスト超過の3つの偽装

Context Length Exceeded
3つの偽装形態、最後が最も見分けにくい

同じコンテキスト超過でも、明示的に 400 を返す場合、入力を静かに切り詰める場合、外側は 200 なのにストリームが空の場合がある——3つ目が最も見分けにくい。

#context_length_exceeded#maximum context length#静かな切り詰め#空ストリーム調査

4つの重要事実

400

明示的エラー(最も分かりやすい)

エラーボディに context_length_exceeded や maximum context length という文字列が直接現れ、原因が一目瞭然。

静かな切り詰め

入力の一部がこっそり切り捨てられる

一部のクライアント/ゲートウェイは超過を検知すると、エラーを出さずに古いメッセージを自動的に切り捨てる。モデルが見るコンテキストは想定より少なく、出力が「忘れっぽく」見える。

200 で空ストリーム

最も見分けにくいパターン

HTTP ステータスは 200 なのに、ストリーミング応答が接続直後に何もトークンを出さず終了する——ネットワーク問題やクライアントのバグと誤診されやすい。

分割/RAG

根本的な対処法

長いコンテキストを分割する、要約や検索拡張生成(RAG)を使う、より大きなコンテキストウィンドウのモデルに切り替える——これが3つの偽装すべてに共通する根本対策。

3つの偽装がそれぞれどう見えるか

1つ目、明示的な 400:レスポンスボディに context_length_exceeded や maximum context length という文字列が直接現れ、リクエスト全体が拒否される——最も特定しやすい。2つ目、静かな切り詰め:一部の SDK、プロキシ層、履歴管理ロジックは超過が近づくとエラーを出さずに最も古いメッセージを自動的に破棄する。モデルはリクエストを受け取り正常に応答するが、切り捨てられた部分が見えないため、出力は「前に言ったことを忘れた」ように、または矛盾しているように見える。3つ目、外側は 200 だがストリームが空:HTTP レベルではすべて正常でステータス 200 だが、ストリーミング接続が確立された直後にトークンが1つも出ないまま終了する——ネットワークの揺らぎ、タイムアウト、クライアントの解析バグと最も誤診されやすい。実際の根本原因は、リクエストがすでにコンテキストウィンドウを超過し、ストリーミング開始前にサーバー側で失敗と判定されているが、標準的な 400 エラーボディがストリーミングプロトコルに伝播されていないだけ、というケースが多い。

最近この問題が増えている理由

エージェント/サブエージェントのワークフローが広まるにつれ、1回のリクエストにコードベース全体、完全な会話履歴、複数ラウンドのツール呼び出し結果を詰め込むケースが増え、コンテキストウィンドウを超過する確率が大きく上昇している。さらにクライアントやゲートウェイごとに超過時の扱いが異なり(エラーを出す、静かに切り詰める、空ストリームになるなど)、原因の切り分けも難しくなっている。

タイムライン

継続中

context_length_exceeded は主要モデル API に長く存在する標準的なエラータイプで、コンテキストウィンドウという概念自体と同じくらい古い。

最近

エージェント/サブエージェントのワークフローにより、1回のリクエストに含まれるコンテキスト量が大幅に増加し、上限に達するケースが増えている。

継続中

最も見分けにくい「外側 200、ストリーム空」という偽装が、フルエージェント型のワークフローで増加しており、最も誤診されやすいパターンになっている。

確認済み vs よくある誤解

確認済み

3つの偽装形態(明示的な 400、静かな切り詰め、外側 200 の空ストリーム)はいずれも公開されている開発者の議論や各種 SDK/ゲートウェイの実装で確認できる。根本原因はすべて同じ——リクエスト内容(履歴、ツール呼び出し結果、システムプロンプトを含む)がモデルのコンテキストウィンドウ上限を超えていること。

よくある誤解

空ストリームに遭遇すると、多くの人はまずネットワークやクライアントの故障を疑い、何度もリトライしたりネットワーク環境を変えたりする。しかし根本原因が超過であれば、これらの対処はどれも効果がなく、調査の時間を無駄にするだけだ。

この問題かどうかを素早く見分ける方法

まずリクエストのサイズを見る

今回のリクエストが実際に運んだトークン数(システムプロンプト+履歴+ツール呼び出し結果+新規入力)を集計し、モデルが公表するコンテキストウィンドウ上限と比較する。超過または近い場合はこの方向を疑うべきだ。

次にレスポンスの形を見る

明示的な 400 ならそのまま確認できる。静かな切り詰めはモデルの出力が「忘れっぽい」かどうかで判断する。外側 200 の空ストリームは、ストリーミング接続確立直後にトークンなしで終了しているか(タイムアウトではなく)を見る。

特定と解決の手順

第1歩、今回のリクエストの総トークン数を(公式のトークナイザーやサードパーティの推定ツールで)見積もり、モデルのコンテキストウィンドウ上限と比較する。第2歩、上限に近いか超えていると確認できたら、優先すべきはリトライではなく入力の簡素化——履歴を要約して圧縮する、直近の数ラウンドだけ残す、あるいは全履歴を詰め込む代わりに検索拡張生成(RAG)で関連部分だけ取得する。第3歩、タスク自体が本当に長いコンテキストを必要とするなら、より大きなコンテキストウィンドウのモデルへの切り替えを検討する。第4歩、「外側 200、空ストリーム」のケース専用に、ストリーミング応答が確立してから短時間トークンが来なければ、単純なネットワークタイムアウトとしてリトライするのではなく、超過として扱う判定を追加する。

QCode 上での対処法

QCode のモデルラインナップには、コンテキストウィンドウのサイズが異なる複数のファミリーがある。同じキーでタスクの規模に応じてより大きなコンテキストウィンドウのモデルティアに切り替えられ、長いコンテキストのために特別な申請や設定は不要だ。

よくある質問

自分がこの問題に当たったかどうか、どう判断しますか?

まず今回のリクエストの総トークン数を集計し、モデルが公表するコンテキストウィンドウと比較する。上限に近いか超えていて、かつレスポンスが明示的な 400、矛盾した(切り詰められた疑いのある)出力、またはトークンなしで終わるストリーミング応答であれば、ほぼ確定できる。

静かな切り詰めはなぜエラーにならないのですか?

一部のクライアント/ゲートウェイが自前で実装しているフォールトトレランス処理だ。超過を検知すると、リクエスト全体を失敗させる代わりに最も古いメッセージを破棄し、会話が「続いているように」見せる。その代償として、モデルは切り捨てられたコンテキストを見られなくなる。

外側 200 なのにストリームが空なのは、ネットワークの問題ですか?

通常は違う。よくある根本原因は、リクエストがサーバー側で超過によりすでに失敗と判定されているが、基盤側が標準的な 400 エラーボディをストリーミングプロトコルに伝播していないため、クライアント側からは「接続は成功したがコンテンツがない」ように見えるというものだ。同じ長すぎるリクエストをリトライしても、また空ストリームになる可能性が高い。

1回のリクエストで実際に何トークン使ったか、どう見積もればいいですか?

システムプロンプト、完全な履歴メッセージ、ツール呼び出し結果、新規入力をすべて合算し、公式のトークナイザーやサードパーティの推定ツールで集計する。エージェント/サブエージェントのシナリオでは特に過小評価しやすい。各ラウンドのツール呼び出し結果が次のリクエストに再び詰め込まれるためだ。

より大きなコンテキストウィンドウのモデルに切り替えれば、これで解決しますか?

緩和にはなるが、無限ではない——コンテキストウィンドウが大きいほど、1回あたりのリクエストコストも通常上がり、どれだけ大きくても上限はある。より確実なのは、入力の簡素化(要約、RAG)も同時に行い、ウィンドウサイズを唯一の頼みではなく余裕分として扱うことだ。

この問題は 429/429 や 529 のようなエラーと同じですか?

違う。429/529 はレートや容量の問題であり、リクエスト内容のサイズとは無関係だ。context_length_exceeded はリクエスト内容自体がモデルの処理上限を超えていることを意味し、速度を落としたりバックオフでリトライしたりしても解決しない。

情報源

3つの偽装形態は、公開されている開発者の議論と各社モデル API の標準的なエラータイプの説明をもとに整理した。本ページは特定のベンダーの非公開実装の詳細について断定はせず、ベンダー横断で共通して見られる現象と見分け方のみを扱う。2026-08-27 時点で整理。

コンテキスト超過で開発を止めない

QCode の1つのキーでタスクの規模に応じてより大きなコンテキストウィンドウのモデルティアに切り替え。

関連記事

本ページはベンダー横断の一般的な技術解説であり、特定のベンダーの非公開実装について断定するものではありません。実際の挙動は使用するモデルとクライアントのドキュメントに従います。