Guard error.message with rescue in LLM failed-usage recording (#1144)

* Initial plan

* Fix nil references in Recording failed LLM usage code paths

Co-authored-by: jjmata <187772+jjmata@users.noreply.github.com>

* Replace error&.message with rescue-guarded safe_error_message helper

error&.message only guards against nil; it still raises when the error
object's .message implementation itself throws (e.g. OpenAI errors that
call data on nil). Replace with a safe_error_message helper that wraps
error&.message in a rescue block, returning a descriptive fallback
string on secondary failures. Apply the helper in both record_usage_error
(usage_recorder.rb) and record_llm_usage (openai.rb), including the
regex branch of extract_http_status_code in both files.

Co-authored-by: jjmata <187772+jjmata@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jjmata <187772+jjmata@users.noreply.github.com>
This commit is contained in:
Copilot
2026-03-07 18:49:13 +01:00
committed by GitHub
parent df650b0284
commit a07b1f00c3
2 changed files with 19 additions and 7 deletions

View File

@@ -538,7 +538,7 @@ class Provider::Openai < Provider
# For error cases, record with zero tokens
if error.present?
Rails.logger.info("Recording failed LLM usage - Error: #{error.message}")
Rails.logger.info("Recording failed LLM usage - Error: #{safe_error_message(error)}")
# Extract HTTP status code if available from the error
http_status_code = extract_http_status_code(error)
@@ -553,7 +553,7 @@ class Provider::Openai < Provider
total_tokens: 0,
estimated_cost: nil,
metadata: {
error: error.message,
error: safe_error_message(error),
http_status_code: http_status_code
}
)
@@ -614,11 +614,17 @@ class Provider::Openai < Provider
error.status_code
elsif error.respond_to?(:response) && error.response.respond_to?(:code)
error.response.code.to_i
elsif error.message =~ /(\d{3})/
elsif safe_error_message(error) =~ /(\d{3})/
# Extract 3-digit HTTP status code from error message
$1.to_i
else
nil
end
end
def safe_error_message(error)
error&.message
rescue => e
"(message unavailable: #{e.class})"
end
end

View File

@@ -47,15 +47,15 @@ module Provider::Openai::Concerns::UsageRecorder
# Records failed LLM usage for a family with error details
def record_usage_error(model_name, operation:, error:, metadata: {})
return unless family
return unless family && error
Rails.logger.info("Recording failed LLM usage - Operation: #{operation}, Error: #{error.message}")
Rails.logger.info("Recording failed LLM usage - Operation: #{operation}, Error: #{safe_error_message(error)}")
# Extract HTTP status code if available from the error
http_status_code = extract_http_status_code(error)
error_metadata = metadata.merge(
error: error.message,
error: safe_error_message(error),
http_status_code: http_status_code
)
@@ -86,11 +86,17 @@ module Provider::Openai::Concerns::UsageRecorder
error.status_code
elsif error.respond_to?(:response) && error.response.respond_to?(:code)
error.response.code.to_i
elsif error.message =~ /(\d{3})/
elsif safe_error_message(error) =~ /(\d{3})/
# Extract 3-digit HTTP status code from error message
$1.to_i
else
nil
end
end
def safe_error_message(error)
error&.message
rescue => e
"(message unavailable: #{e.class})"
end
end