Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions lib/ruby_llm/providers/openrouter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,35 @@ def headers
}
end

def parse_error(response)
return if response.body.empty?

body = try_parse_json(response.body)
case body
when Hash
parse_error_part_message body
when Array
body.map do |part|
parse_error_part_message part
end.join('. ')
else
body
end
end

private

def parse_error_part_message(part)
message = part.dig('error', 'message')
raw = try_parse_json(part.dig('error', 'metadata', 'raw'))
return message unless raw.is_a?(Hash)

raw_message = raw.dig('error', 'message')
return [message, raw_message].join(' - ') if raw_message

message
end

class << self
def configuration_requirements
%i[openrouter_api_key]
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions spec/ruby_llm/providers/openrouter/parse_error_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe RubyLLM::Providers::OpenRouter do # rubocop:disable RSpec/SpecFilePathFormat
describe '#parse_error' do
model = 'openai/o3-mini'
provider = 'openrouter'
context "with #{provider}/#{model}" do
let(:chat) { RubyLLM.chat(model: model, provider: provider) }

before do
RubyLLM.config.openrouter_api_key = 'sk-or-v1-sk-or-v1-mocked-key'
end

it 'raises detailed error' do
expect { chat.ask('Hello') }.to raise_error do |error|
expect(error).to be_a(RubyLLM::Error)
expect(error.message).to eq 'Provider returned error - Country, region, or territory not supported'
end
end
end
end
end