From a07b1f00c3afc7fb8af70bd06b9588555b04ec77 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 18:49:13 +0100 Subject: [PATCH] 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> --- app/models/provider/openai.rb | 12 +++++++++--- .../provider/openai/concerns/usage_recorder.rb | 14 ++++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/app/models/provider/openai.rb b/app/models/provider/openai.rb index 154b2d02e..993a32a43 100644 --- a/app/models/provider/openai.rb +++ b/app/models/provider/openai.rb @@ -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 diff --git a/app/models/provider/openai/concerns/usage_recorder.rb b/app/models/provider/openai/concerns/usage_recorder.rb index 55f94f052..ef552dfd1 100644 --- a/app/models/provider/openai/concerns/usage_recorder.rb +++ b/app/models/provider/openai/concerns/usage_recorder.rb @@ -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