Skip to content

Cap search pagination at the OpenSearch result window; surface search errors - #1683

Open
JasonWildMe wants to merge 3 commits into
mainfrom
fix/search-pagination-window-ui
Open

Cap search pagination at the OpenSearch result window; surface search errors#1683
JasonWildMe wants to merge 3 commits into
mainfrom
fix/search-pagination-window-ui

Conversation

@JasonWildMe

Copy link
Copy Markdown
Collaborator

Fixes #1681
Companion to #1682 (backend), which adds the X-Wildbook-Max-Result-Window header this PR consumes. Works standalone too — a 10,000 default applies when the header is absent.

What

  • utils/resultWindow.js (new): pure pagination-window math. Inside the window a partial last page is kept; when the result set exceeds the window, only full pages are offered so no request can straddle the ceiling (e.g. window 10,000 at 30/page previously implied page 334 → from=9990&size=30 = 10,020, which the backend refuses).
  • DataTable.jsx: the paginator and "Go to page" input offer only browsable pages; when results are capped, a localized notice explains that only the first N of M results can be browsed; an error prop renders a localized "search failed" message instead of a misleading "No results found"; changing per-page resets to page 1 and a clamp effect snaps the page back if the browsable count shrinks; the paginator is not rendered at zero pages.
  • useFilterEncounters.js: exposes the window header, and retries only transport/5xx failures — a deterministic 4xx (like a pagination rejection) is no longer retried twice per click.
  • EncounterSearch.jsx: passes error state and the per-branch window limit (the stored-query path reads the header from its own response).
  • New UI copy localized in de/en/es/fr/it.

Why

Production incident 2026-07-10: for >window search results the UI offered terminal page links the backend can never serve; the resulting 500 was swallowed into an empty "No results found" table, so the user retried repeatedly — each click costing 3 requests (react-query retry) × 6 OpenSearch executions (backend retry bug, fixed in #1682).

Tests / verification

  • resultWindow.test.js: 11 cases including the straddle case, per-index 12,004 window, boundary and invalid inputs. All green.
  • Full CRA production build compiles with no new warnings (react-hooks/exhaustive-deps clean on all touched code).
  • Reviewed by Codex (gpt-5.6, high reasoning), three rounds to convergence: round 1 — 2 Majors (straddling final page, unclamped page state) fixed; round 2 — 1 Major (query-ID branch window) + 1 Low (zero-page paginator warning) fixed; round 3 — converged, no findings.

Follow-up (out of scope, noted in #1681): search_after cursor pagination to make all results browsable.

🤖 Generated with Claude Code

JasonWildMe and others added 3 commits July 10, 2026 16:35
… errors

- DataTable offers only pages inside index.max_result_window (via the
  X-Wildbook-Max-Result-Window header when available, defaulting to 10000)
  instead of terminal page links the backend can never serve; when capped, a
  localized notice explains that only the first N results are browsable
- the "Go to page" input honors the same ceiling
- an error state now renders a localized "search failed" message instead of
  a misleading "No results found" empty table
- useFilterEncounters exposes the window header and no longer retries 4xx
  responses (deterministic failures were retried twice per click)
- new UI copy localized in de/en/es/fr/it

Fixes #1681

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- pageCount uses floor for capped result sets so the final offered page's
  from+size never straddles the window (window 10000 at 30/page previously
  offered page 334 = from 9990 + size 30 = 10020, refused by the backend);
  partial last pages remain for result sets inside the window
- browsableItemCount reports the actually reachable item count (pages x
  perPage when capped) so the capped notice is accurate
- changing per-page resets to the first page, and a clamp effect snaps the
  page back whenever the browsable page count drops below it; forcePage is
  clamped to the cap

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ero pages

- the query-ID search now reads x-wildbook-max-result-window from its OWN
  response and the table receives the branch-appropriate limit, so stored
  searches on indexes with a raised window are no longer capped at 10k (and
  smaller windows can no longer offer invalid pages)
- the paginator is not rendered when the browsable page count is zero,
  avoiding react-paginate's controlled-page warning during initial load

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 50.00000% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 51.49%. Comparing base (67ed0ed) to head (8e5980c).

Files with missing lines Patch % Lines
frontend/src/components/DataTable.jsx 0.00% 15 Missing ⚠️
...ntend/src/models/encounters/useFilterEncounters.js 0.00% 3 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1683      +/-   ##
==========================================
- Coverage   51.49%   51.49%   -0.01%     
==========================================
  Files         311      312       +1     
  Lines       12261    12299      +38     
  Branches     3956     3865      -91     
==========================================
+ Hits         6314     6333      +19     
- Misses       5665     5683      +18     
- Partials      282      283       +1     
Flag Coverage Δ
backend 51.49% <50.00%> (-0.01%) ⬇️
frontend 51.49% <50.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@naknomum
naknomum self-requested a review July 15, 2026 20:32
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.

Search results: pages beyond the OpenSearch result window render an empty table with no error

2 participants