Skip to content

Return an empty page instead of 500ing on out-of-range wishlist product pages#6082

Merged
gumclaw merged 1 commit into
mainfrom
fix/wishlist-products-pagy-overflow
Jul 21, 2026
Merged

Return an empty page instead of 500ing on out-of-range wishlist product pages#6082
gumclaw merged 1 commit into
mainfrom
fix/wishlist-products-pagy-overflow

Conversation

@gumclaw

@gumclaw gumclaw commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

What

Public wishlist product listings (Wishlists::ProductsController#indexWishlistPresenter#paginated_public_items) now return an empty page instead of raising Pagy::OverflowError when the requested ?page= exceeds the total page count.

Why

Sentry GUMROAD-2APagy::OverflowError: expected :page in 1..1; got 2 — has fired 1,614 times for 566 users since March 2026 and is still firing daily. The endpoint is public and unauthenticated: the page number comes straight from the query string, so out-of-range pages arrive constantly (stale bookmarks, crawlers, wishlists whose products were removed between page loads). Each one 500ed.

The repo's global pagy default is overflow: :exception (config/initializers/pagy.rb), and other public paginated presenters already opt out per-call (paginated_installments_presenter.rb uses overflow: :empty_page, affiliated_products_presenter.rb/paginated_utm_links_presenter.rb use :last_page). This applies the same pattern here. :empty_page (not :last_page) so the client's "load more" pagination terminates cleanly with next: nil instead of re-serving the last page's items.

A prior attempt (#4116) rescued the error in the presenter and fell back to page 1; it was closed for inactivity. Pagy's built-in overflow mode is simpler and matches existing convention.

QA steps

  1. Create a wishlist with fewer than 20 products.
  2. Request https://<seller>.gumroad.com/wishlists/<id>/products?page=2.
  3. Before: 500. After: 200 with {"items": [], "pagination": {"page": 2, "pages": 1, "next": null, ...}}.

Test Results

bundle exec rspec spec/presenters/wishlist_presenter_spec.rb28 examples, 0 failures. The new spec ("returns an empty page instead of raising when the requested page exceeds the total pages") was proven red against unmodified main before the fix.

spec results

Before/After

Not a UI change — valid in-range pages render byte-identical data (all 27 pre-existing presenter specs pass unmodified). Only the out-of-range error path changes from a 500 to an empty JSON page.


AI disclosure: Generated with Claude Fable 5 (Gumclaw's daily Sentry sweep cron). Instructions: triage top unresolved Sentry issues in the gumroad project, classify, and fix actionable items with red-first tests per the repo's contribution gates.

…ct pages

Public wishlist product listings (Wishlists::ProductsController#index) raised
Pagy::OverflowError when the requested ?page= exceeded the total page count,
returning a 500 to stale links and crawlers. Use pagy's overflow: :empty_page
so out-of-range pages return an empty items list with pagination metadata,
matching the pattern already used by other public paginated presenters.

Fixes Sentry GUMROAD-2A (1,614 events / 566 users since March).
@gumclaw gumclaw self-assigned this Jul 21, 2026
@gumclaw
gumclaw enabled auto-merge (squash) July 21, 2026 12:11
@gumclaw

gumclaw commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

Self-review (fable-5 adversarial pass on the diff):

  • Scope of the change: paginated_public_items is called only from public_items, whose only caller is Wishlists::ProductsController#index (grep-verified). No other consumer's overflow behavior changes.
  • Why :empty_page and not :last_page: the frontend consumes pagination.next for load-more; :empty_page yields next: nil and an empty items array, which terminates pagination cleanly. :last_page would re-serve duplicate items to a client that explicitly asked for a later page.
  • Pagy extras: pagy/extras/overflow is already required globally in config/initializers/pagy.rb (the repo-wide default is overflow: :exception), so the per-call override needs no new require.
  • Red→green proof: the new spec fails on unmodified main with Pagy::OverflowError: expected :page in 1..1; got 2 (the exact production error) and passes with the fix. All 27 pre-existing specs pass unmodified, confirming in-range pages are byte-identical.
  • No P1/P2 findings.

@greptile-apps

greptile-apps Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR makes out-of-range public wishlist pages return an empty result instead of an error. The main changes are:

  • Uses Pagy’s empty_page overflow mode for public wishlist products.
  • Adds a test for an out-of-range page request.
  • Adds a QA image showing the focused presenter test results.

Confidence Score: 5/5

This looks safe to merge.

No blocking issues were found in the changed code. The overflow option follows an existing repository pattern, and the new test covers the reported out-of-range request.

T-Rex T-Rex Logs

What T-Rex did

  • The focused RSpec run exited with code 127 because bundler could not find the rspec command.
  • The bundle check exited with code 18, confirming a Ruby version conflict with the repository's Ruby 3.4.3 requirement.
  • The ruby -c syntax checks on the presenter and the focused spec reported Syntax OK, indicating no syntax errors there.
  • Validation is blocked by the environment rather than an executed contradiction in the changed code.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
app/presenters/wishlist_presenter.rb Adds a per-call overflow policy that returns an empty collection when the requested page exceeds the available pages.
spec/presenters/wishlist_presenter_spec.rb Tests that page 2 of a one-product wishlist returns empty items and terminal pagination metadata.
qa-media/pr-wishlist-pagy-overflow-spec-results.png Adds a QA artifact for the focused presenter test run.

Reviews (1): Last reviewed commit: "Return an empty page instead of 500ing o..." | Re-trigger Greptile

@gumclaw
gumclaw merged commit 87bffc0 into main Jul 21, 2026
86 checks passed
@gumclaw
gumclaw deleted the fix/wishlist-products-pagy-overflow branch July 21, 2026 12:27
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.

1 participant