⚡ Solution Summary

  • The issue was caused by starting_after being None in the parameters.
  • A fix was implemented in PR #1563.
  • The fix was released in version 12.5.1.
### Describe the bug I was working with the `auto_paging_iter` to implement Relay pagination over invoices, and I encountered an interesting quirk in the way it is implemented. The `auto_paging_iter` code currently checks if `ending_before` is in the retrieve params and `starting_after` is not to decide to reverse the results and paginate backwards: ```python def _auto_paging_iter(self) -> Iterator[T]: page = self while True: if ( "ending_before" in self._retrieve_params and "starting_after" not in self._retrieve_params ): for item in reversed(page): yield item page = page.previous_page() else: for item in page: yield item page = page.next_page() if page.is_empty: break ``` In my code I am passing along all input args because, at least in the services model, the SDK correctly ignores and drops any `params` passed as `None`: ```python for stripe_invoice in stripe_client.v1.invoices.list( params={ "limit": 100, "customer": dynamodb_alarm_user.customer_id, "starting_after": parsed_input.after, "ending_before": parsed_input.before, "expand": ("data.customer",), }, options=merge_default_options( {"stripe_account": dynamodb_jurisdiction.account_id} ), ).auto_paging_iter(): ``` This leads to the following params being shown in the request logs on Stripe's side: ```json { "customer": "cus_SyBoRWyoh9GtxR", "ending_before": "in_1S2FQhBARyXc9bEw3n0eQQwj", "expand": { "0": "data.customer" }, "limit": "100" } ``` However, because `starting_after` is present in `self._retrieve_params` even though it is `None`, the `auto_paging_iter` logic falls into the else cases and does not reverse the results and calls `page.next_page()` instead of `page.previous_page()`. This leads to an incorrect pagination after the first page of results, because it uses the wrong cursors and arguments to retrieve the next page. ### To Reproduce 1. create N invoices to be able to paginate over under the same stripe account. 2. use `stripe_client.v1.invoices.list(params={"limit": 1, "starting_after": None, "ending_before": invoices[-1].id}).auto_paging_iter()` to try and iterate the results. ### Expected behavior The auto paging iter should iterate backwards over the invoices list from the end to the beginning, excluding the invoice specified as `ending_before`. ### Code snippets ```Python ``` ### OS Ubuntu 22.04.5 LTS ### Language version Python 3.13.3 ### Library version 12.5.0 ### API version 2025-08-27.basil ### Additional context _No response_

Discussion & Fixes

mbroshi-stripe 2025-09-02
👋 Hi @ryancausey ! Thanks for reporting this issue, and the carefully written description! I will begin investigating this issue and circle back as needed.
mbroshi-stripe 2025-09-02
Following up here: 1. Thanks for putting up a [fix](https://github.com/stripe/stripe-python/pull/1563)! I'll review more closely, but it looks good at first blush. 2. While investigating this issue, I also realized we have an unrelated bug that subsequent paginations will fail if `limit` is smaller than the number of objects in the list. I'll review your PR, and fix the second issue separately.
ryancausey 2025-09-05
> 2. While investigating this issue, I also realized we have an unrelated bug that subsequent paginations will fail if `limit` is smaller than the number of objects in the list. I can open up a new issue for this if you would like? That sounds like a big problem.
mbroshi-stripe 2025-09-05
@ryancausey It actually turned out that your PR fixed both! Thanks again for bringing up and fixing the issue. 🚀 I just released it as [v12.5.1](https://github.com/stripe/stripe-python/releases/tag/v12.5.1).

Get updates

We publish verified fixes weekly. No spam.

Subscribe