From 6891a9a313232087476e6c02e9c4947967661491 Mon Sep 17 00:00:00 2001 From: vitorcastro Date: Tue, 9 Jun 2026 19:03:00 +0200 Subject: [PATCH 1/2] Include API error message in exception when log_errors is enabled When the OpenAI API returns an error response, the exception message only contained the HTTP status code and URL, making it difficult to debug the actual cause of the error. This change extracts the error message from the response body and appends it to the exception message when MiddlewareErrors is active (i.e. when log_errors is set to true). Before: 'the server responded with status 400 for POST ...' After: 'the server responded with status 400 for POST ... - Invalid content type. image_url is only supported by certain models.' Fixes #634 --- lib/openai.rb | 17 ++++++++++------- spec/openai/client/http_spec.rb | 9 +++++++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/lib/openai.rb b/lib/openai.rb index d5880c90..2d073a6c 100644 --- a/lib/openai.rb +++ b/lib/openai.rb @@ -29,15 +29,18 @@ class ConfigurationError < Error; end class AuthenticationError < Error; end class MiddlewareErrors < Faraday::Middleware - def call(env) - @app.call(env) - rescue Faraday::Error => e - raise e unless e.response.is_a?(Hash) + def call(env) + @app.call(env) + rescue Faraday::Error => e + raise e unless e.response.is_a?(Hash) - OpenAI.log_message("OpenAI HTTP Error", e.response[:body], :error) - raise e - end + OpenAI.log_message("OpenAI HTTP Error", e.response[:body], :error) + + body = e.response[:body] + api_message = body.is_a?(Hash) ? body.dig("error", "message") : nil + raise e, api_message ? "#{e.message} - #{api_message}" : e.message end +end class Configuration attr_accessor :access_token, diff --git a/spec/openai/client/http_spec.rb b/spec/openai/client/http_spec.rb index 471289f4..37a5c605 100644 --- a/spec/openai/client/http_spec.rb +++ b/spec/openai/client/http_spec.rb @@ -258,12 +258,18 @@ VCR.use_cassette(cassette, record: :none) do expect { OpenAI::Client.new(log_errors: log_errors).models.retrieve(id: "text-ada-001") } .to raise_error Faraday::Error - $stdout.rewind captured_stdout = $stdout.string expect(captured_stdout).to include("OpenAI HTTP Error") end end + + it "includes the API error message in the exception" do + VCR.use_cassette(cassette, record: :none) do + expect { OpenAI::Client.new(log_errors: log_errors).models.retrieve(id: "text-ada-001") } + .to raise_error(Faraday::Error, /Test error/) + end + end end describe "when log_errors is set to false" do @@ -273,7 +279,6 @@ VCR.use_cassette(cassette, record: :none) do expect { OpenAI::Client.new(log_errors: log_errors).models.retrieve(id: "text-ada-001") } .to raise_error Faraday::Error - $stdout.rewind captured_stdout = $stdout.string expect(captured_stdout).not_to include("OpenAI HTTP Error") From 8c9e9605d0b7203900f69147c8747f69740fb161 Mon Sep 17 00:00:00 2001 From: vitorcastro Date: Tue, 9 Jun 2026 19:08:29 +0200 Subject: [PATCH 2/2] Fix RuboCop indentation offenses in MiddlewareErrors --- lib/openai.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/openai.rb b/lib/openai.rb index 2d073a6c..14cf2777 100644 --- a/lib/openai.rb +++ b/lib/openai.rb @@ -29,18 +29,18 @@ class ConfigurationError < Error; end class AuthenticationError < Error; end class MiddlewareErrors < Faraday::Middleware - def call(env) - @app.call(env) - rescue Faraday::Error => e - raise e unless e.response.is_a?(Hash) + def call(env) + @app.call(env) + rescue Faraday::Error => e + raise e unless e.response.is_a?(Hash) - OpenAI.log_message("OpenAI HTTP Error", e.response[:body], :error) + OpenAI.log_message("OpenAI HTTP Error", e.response[:body], :error) - body = e.response[:body] - api_message = body.is_a?(Hash) ? body.dig("error", "message") : nil - raise e, api_message ? "#{e.message} - #{api_message}" : e.message + body = e.response[:body] + api_message = body.is_a?(Hash) ? body.dig("error", "message") : nil + raise e, api_message ? "#{e.message} - #{api_message}" : e.message + end end -end class Configuration attr_accessor :access_token,