Skip to content

api: Add auto_retry_rate_limits option to Client to handle 429 errors#908

Open
sohampanda000 wants to merge 1 commit intozulip:mainfrom
sohampanda000:rate-limit-retry
Open

api: Add auto_retry_rate_limits option to Client to handle 429 errors#908
sohampanda000 wants to merge 1 commit intozulip:mainfrom
sohampanda000:rate-limit-retry

Conversation

@sohampanda000
Copy link
Copy Markdown
Collaborator

@sohampanda000 sohampanda000 commented Mar 13, 2026

My Pull Request (PR) adds the boolean auto_retry_rate_limits as a parameter in the Client class in __init__.py of the Python Zulip API.

Fixes:

  • Python's API Library does not handle HTTP 429 (RATE_LIMIT_HIT) errors automatically. If a client exceeds the message limit, Python will throw an error and forces users to manually implement a method to pause the thread and try again.

  • To resolve this, the __init__ constructor of the Client class has been given a new addition of an opt-in parameter initialized to False to keep existing behavior. This catches the 429 status code in this function: do_api_query().

  • So, it is ensured that the client safely parses the retry-after value, pauses the sleep thread using the time.sleep() function, and finally tries the message request again without failure.

How changes were tested:

  • Continuous Pipeline (CI) Testing: I pushed the commit, via git push, to trigger the GitHub Actions CI Suite. This commit sustains the code through standard API testing suits. Additionally, the zulint linter checks Python formatting and that no client configurations have broke.

  • Testing Verification: After verifying everything, I made sure of the try/catch code block for parsing retry-after defaults to 1 seconds only if the JSON (body or header) is unusual at all.

Fixes: #773

Self-review checklist
  • Self-reviewed the changes for clarity and maintainability
    (variable names, code reuse, readability, etc.).

Communicate decisions, questions, and potential concerns.

  • Explains differences from previous plans (e.g., issue description).
  • Highlights technical choices and bugs encountered.
  • Calls out remaining decisions and concerns.
  • Automated tests verify logic where appropriate.

Individual commits are ready for review (see commit discipline).

  • Each commit is a coherent idea.
  • Commit message(s) explain reasoning and motivation for changes.

Completed manual review and testing of the following:

  • Visual appearance of the changes.
  • Responsiveness and internationalization.
  • Strings and tooltips.
  • End-to-end functionality of buttons, interactions and flows.
  • Corner cases, error conditions, and easily imagined bugs.

@sohampanda000 sohampanda000 changed the title api: Add auto_retry_rate_limits option to Client to handle 429 errors. api: Add auto_retry_rate_limits option to Client to handle 429 errors Mar 13, 2026
@alya
Copy link
Copy Markdown
Contributor

alya commented Mar 13, 2026

Thanks! Please go through our guide on submitting a pull request to learn how to present your proposed changes to Zulip, so that your work can be reviewed.

@sohampanda000
Copy link
Copy Markdown
Collaborator Author

Alya, thank you for the pointer! I updated this PR to follow Zulip's commit discipline by rebasing everything into one commit.

Copy link
Copy Markdown
Contributor

@alexmv alexmv left a comment

Choose a reason for hiding this comment

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

Thanks for this contribuition!

Please add "Fixes: #773" to the commit message, and you can drop "to Client" from the commit message -- all changes in this repo are to the client.

Comment on lines +665 to +667
wait_time = float(
res.json().get("retry-after", res.headers.get("Retry-After", 1.0))
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reading from both is not going to be helpful -- let's just use the header, since the body is slightly more likely to have been potentially corrupted by, e.g., intermediate proxies.

Comment on lines +660 to +661
# On Rate Limit (429) Errors, pause the current thread with time.sleep()
# And only retry if the user opted in sucessfully
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Some typos and weird casing:

Suggested change
# On Rate Limit (429) Errors, pause the current thread with time.sleep()
# And only retry if the user opted in sucessfully
# On Rate Limit (429) errors, retry after the delay the server asked us to wait

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Handle RATE_LIMIT_HIT (Rate limit exceeded) errors

4 participants