diff --git a/lib/ruby_llm/error_middleware.rb b/lib/ruby_llm/error_middleware.rb index 8ebc98508..2a560f22f 100644 --- a/lib/ruby_llm/error_middleware.rb +++ b/lib/ruby_llm/error_middleware.rb @@ -49,7 +49,8 @@ class << self /rate limit/i, /per minute/i, /per hour/i, - /per day/i + /per day/i, + /too many tokens.*please wait/i ].freeze def parse_error(provider:, response:) diff --git a/spec/ruby_llm/error_middleware_spec.rb b/spec/ruby_llm/error_middleware_spec.rb index e9afd70a8..3dbb53d63 100644 --- a/spec/ruby_llm/error_middleware_spec.rb +++ b/spec/ruby_llm/error_middleware_spec.rb @@ -74,6 +74,26 @@ end.to raise_error(RubyLLM::RateLimitError) end + it "maps Bedrock's 'too many tokens, please wait' 429 throttle to RateLimitError, not context length" do + msg = 'Too many tokens, please wait before trying again.' + response = Struct.new(:status, :body).new(429, %({"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::RateLimitError) + end + + it "still maps a 400 'too many tokens' error to ContextLengthExceededError" do + msg = 'Too many tokens in the request' + 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 + it 'maps context-length-like 400 errors to ContextLengthExceededError' do msg = "This model's maximum context length is 8192 tokens." response = Struct.new(:status, :body).new(400, %({"error":{"message":"#{msg}"}}))