-
Notifications
You must be signed in to change notification settings - Fork 4
Enhance error reporting #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
| handle_response(response, decoder, endpoint, params) | ||
| end | ||
|
|
||
| def execute_request(endpoint, params) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extracted to satisfy Rubocop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request enhances error reporting in the SerpApi Ruby client by enriching the SerpApiError exception class with contextual attributes (API error message, search parameters, HTTP status, search ID, and decoder type) and refactoring the error handling logic in the client for better maintainability.
- Enhanced
SerpApiErrorclass with five new optional attributes for detailed error context - Refactored client error handling into focused helper methods with centralized error raising
- Updated version to 1.0.3 and adjusted RuboCop configuration to accommodate the changes
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| lib/serpapi/error.rb | Added new error attributes with validation methods and a to_h serialization method |
| lib/serpapi/client.rb | Refactored error handling into separate methods (execute_request, handle_response, process_json_response, process_html_response, raise_http_error, raise_parser_error) and updated all error raising to include new context attributes |
| spec/serpapi/client/client_spec.rb | Updated test expectations to match new error message format |
| lib/serpapi/version.rb | Bumped version from 1.0.2 to 1.0.3 |
| README.md.erb | Updated gem version reference to 1.0.3 |
| README.md | Updated gem version reference to 1.0.3 |
| .rubocop.yml | Relaxed Metrics/ClassLength and Metrics/ParameterLists constraints to accommodate the enhanced error class |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| serpapi_error: explicit_error || (data ? data[:error] : nil), | ||
| search_params: params, | ||
| response_status: response.status, | ||
| search_id: data&.dig(:search_metadata, :id), |
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The safe navigation operator &. on line 281 only guards against nil, not against data being a type that doesn't respond to dig (like String or Integer). If the JSON response is unexpectedly a primitive value, this would raise a NoMethodError. Consider wrapping this in a check: data.is_a?(Hash) ? data.dig(:search_metadata, :id) : nil or handling this more defensively.
| search_id: data&.dig(:search_metadata, :id), | |
| search_id: data.is_a?(Hash) ? data.dig(:search_metadata, :id) : nil, |
| # @param search_params [Hash, nil] optional hash of the search parameters used | ||
| # @param response_status [Integer, nil] optional HTTP or response status code | ||
| # @param search_id [String, nil] optional id returned by the service for the search | ||
| # @param decoder [String, nil] optional decoder/format used (e.g. "json") |
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation states that the decoder parameter should be a String, but the actual implementation expects a Symbol. The validate_optional_symbol method on line 37 validates it as a Symbol, and line 13 of the class documentation also describes it as a Symbol. Update the parameter documentation to indicate Symbol instead of String.
| # @param decoder [String, nil] optional decoder/format used (e.g. "json") | |
| # @param decoder [Symbol, nil] optional decoder/format used (e.g. :json) |
| end | ||
|
|
||
|
|
||
|
|
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two blank lines were added at the end of this test block. Per Ruby style conventions, there should be only one blank line between test blocks. Remove one of the extra blank lines.
| expect { | ||
| client.send(:get, '/search', :json, {}) | ||
| }.to raise_error(SerpApi::SerpApiError).with_message(/HTTP request failed with error: Missing query `q` parameter./) | ||
| }.to raise_error(SerpApi::SerpApiError).with_message(/HTTP request failed with status: 400.* error: Missing query `q` parameter./) |
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new error attributes (serpapi_error, search_params, response_status, search_id, decoder) are not being tested in the updated test expectations. Given the comprehensive testing approach in this test suite and that these new attributes are a core part of the PR's purpose, consider adding assertions to verify that these attributes are properly populated when errors occur. For example, in the 'missing query' test, you could verify that e.response_status is 400 and e.search_params contains the expected parameters.
| return nil if value.nil? | ||
| raise TypeError, "expected #{name || 'value'} to be a Symbol, got #{value.class}" unless value.is_a?(Symbol) | ||
|
|
||
| value.freeze |
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling freeze on a Symbol is unnecessary since symbols are already immutable in Ruby. While this doesn't cause any issues, you can remove the freeze call on line 79 for consistency with Ruby idioms.
| value.freeze | |
| value |
| # Check for API-level error inside the JSON | ||
| if data.is_a?(Hash) && data.key?(:error) | ||
| raise_http_error(response, data, endpoint, params, explicit_error: data[:error]) | ||
| # Check for HTTP-level error |
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The inline comment on line 265 between the if and elsif clauses reduces readability. Consider moving it above the elsif statement on line 266, or removing it since the elsif condition is self-explanatory.
| # Check for HTTP-level error |
|
|
||
| raise SerpApiError.new( | ||
| "#{msg} from url: https://#{BACKEND}#{endpoint}", | ||
| serpapi_error: explicit_error || (data ? data[:error] : nil), |
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When data is not a Hash (e.g., if the JSON response is an array or primitive value), the fallback data[:error] on line 278 may not behave as expected. While this is unlikely given typical API responses, consider either checking if data is a Hash before accessing data[:error], or simplifying this to just use explicit_error since the fallback case (data[:error]) would be nil anyway when called from line 267 (where we know data doesn't have an :error key or isn't a Hash).
| serpapi_error: explicit_error || (data ? data[:error] : nil), | |
| serpapi_error: explicit_error || (data.is_a?(Hash) ? data[:error] : nil), |
This pull request enhances the
SerpApi::SerpApiErrorclass to include additional details:serpapi_error- The contents of theerrorattribute of the parsed JSON response object, if availablesearch_params- The original query params used for the searchresponse_status- HTTP response statussearch_id- The search id, from the search metadata, from the parsed JSON response object, if availabledecoder- The decoded used in the request (jsonorhtml)With this additional information, client code can print out the search ID for failed searches with something like:
This pull request fixes #15