Skip to content

Conversation

@D-M4rk
Copy link
Contributor

@D-M4rk D-M4rk commented Dec 6, 2025

Closes #901

Description

This PR fixes a crash in chat_github (and other OpenAI-compatible providers) when the API returns a 429 rate limit error with a text body but a Content-Type: application/json header.

Previously, ellmer would crash with a JSON parsing error (lexical error: invalid char in json text) before httr2 could detect the 429 status and trigger a retry.

Changes

  • Updated base_request_error in R/provider-openai-compatible.R.
  • Wrapped resp_body_json() in tryCatch to handle invalid JSON gracefully.
  • Falls back to resp_body_string() if parsing fails, ensuring the error propagates correctly to httr2's retry mechanism.

@D-M4rk D-M4rk marked this pull request as ready for review December 6, 2025 18:56
Copilot AI review requested due to automatic review settings December 6, 2025 18:56
Copy link

Copilot AI left a 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 PR fixes a crash in OpenAI-compatible providers (including chat_github()) when APIs return HTTP 429 rate limit errors with malformed JSON bodies but application/json content-type headers. Previously, the code would crash during JSON parsing before httr2's retry mechanism could handle the 429 status.

Key changes:

  • Added graceful JSON parsing error handling using tryCatch in base_request_error
  • Falls back to plain text response bodies when JSON parsing fails
  • Updated NEWS.md to document the fix

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
R/provider-openai-compatible.R Added error handling to gracefully handle invalid JSON in error responses with JSON content-type
NEWS.md Documented the fix for handling malformed 429 responses

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

if (is_json) {
# Try parsing JSON, but fall back to text if it fails (e.g. 429 text body)
body <- tryCatch(resp_body_json(resp), error = function(e) NULL)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest making a is_json() function like:

is_json <- function(text) {
  tryCatch({
     jsonlite::read_json(text)
     TRUE
  }), function(err) FALSE
}

Then alway use resp_string_string()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated identical, for is_json() helper approach—would you like me to implement that as well, or is the current tryCatch around resp_body_json() sufficient for now?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chat_github crashes on rate limit (429) due to invalid JSON body

2 participants