Anthropicの"prompt is too long"エラーをContextLengthExceededErrorへマッピング
Anthropic API が返す "prompt is too long" エラーメッセージが、RubyLLM で統一的に扱える ContextLengthExceededError に変換されず BadRequestError として送出されていた問題を解消します。エラーハンドリングの一貫性が向上し、呼び出し側はプロバイダーを意識せずに同一例外で対処できるようになります。
背景
Anthropic のコンテキストウィンドウを超えるリクエストでは、400 エラーと共にメッセージ "prompt is too long: <N> tokens > <max> maximum" が返されますが、RubyLLM の ErrorMiddleware が保持する CONTEXT_LENGTH_PATTERNS にこのフレーズが含まれていなかったため、例外は BadRequestError として分類されていました。Issue #755 で報告された通り、他プロバイダーでの ContextLengthExceededError と整合性が取れず、利用者は各プロバイダーごとに例外処理を分岐させる必要がありました。
この不整合は、エラーメッセージパターンの追加という小規模な変更で解決できると判断され、コードベースへの侵入度が低い修正が選択されました。
技術的な変更
ErrorMiddleware の CONTEXT_LENGTH_PATTERNS 配列に正規表現 /prompt is too long/i を追加し、Anthropic 固有のエラーメッセージを一致させます。変更前後を抜粋すると次のようになります。
@@ -27,7 +27,8 @@ class << self
/token count exceeds/i,
/input[_\s-]?token/i,
/input or output tokens? must be reduced/i,
- /reduce the length of messages/i
+ /reduce the length of messages/i,
+ /prompt is too long/i
].freeze
この追加に伴い、テストスイートにも Anthropic のエラーメッセージを対象としたケースを加えました。テストは ErrorMiddleware.parse_error が期待通り ContextLengthExceededError を送出することを検証します。
it "maps Anthropic's 'prompt is too long' 400 error to ContextLengthExceededError" do
msg = 'prompt is too long: 209025 tokens > 200000 maximum'
response = Struct.new(:status, :body).new(400, %({"error":{"message":"#{msg}"}}))
provider = instance_double(RubyLLM::Provider, parse_error: msg)
expect do
described_class.parse_error(provider: provider, response: response)
end.to raise_error(RubyLLM::ContextLengthExceededError)
end
これらの変更は API 互換性を保持 しつつ、エラーハンドリングのロジックを拡張するだけで済んでいます。
設計判断
エラーパターンを 既存の CONTEXT_LENGTH_PATTERNS 配列に追加 する方針が採られました。新規設定キーや専用クラスを導入せず、配列に正規表現を一つ足すだけで済むため、後方互換性 が最大限保たれます。さらに、正規表現は大文字小文字を無視する /i フラグを付与しているため、Anthropic が将来的にメッセージの大小文字を変えてもマッピングが失敗しにくくなります。
この設計は、例外階層を変えずに コンテキスト長エラーの一元管理 を実現するというライブラリの基本方針に沿っており、変更点が限定的であることからリグレッションリスクも低減されています。
まとめ
Anthropic の "prompt is too long" エラーメッセージが ContextLengthExceededError に正しくマッピングされるよう CONTEXT_LENGTH_PATTERNS が拡張され、テストで検証されました。結果として、RubyLLM 利用者はプロバイダーに依存せず同一例外でコンテキスト長超過を捕捉でき、コードベースへの影響は最小限に抑えられました。