FA-8606 / Client navigation / Open access
Pagination button state: Empty results display a nonexistent first page · case 01
Empty results display a nonexistent first page.
ROOT CAUSE
The empty operation uses `if pages == 0: return (1, False, False)` where the contract requires `if pages == 0: return (0, False, False)`.
VERIFIED REPAIR
Implement the empty operation as `if pages == 0: return (0, False, False)`.
Unsuccessful approach: Enabling navigation on empty results offers unusable controls.
Case contract
Empty pagination uses page zero with disabled controls; nonempty page clamps to 1..pages; actions move by one or to endpoints; availability reflects resulting page.
Why this case matters
A deterministic model of pagination button state; this isolates one interface invariant without requiring a browser.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(page, pages, action):
if pages == 0: return (1, False, False)
page = max(1, min(page, pages))
if action == 'first': page = 1
elif action == 'last': page = pages
elif action == 'next': page = min(pages, page+1)
elif action == 'previous': page = max(1, page-1)
return (page, page > 1, page < pages)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('empty', solve(1, 0, "none"), (0, False, False))
check('shrink', solve(8, 3, "none"), (3, True, False))
check('zero', solve(0, 3, "none"), (1, False, True))
check('last', solve(1, 5, "last"), (5, True, False))
check('next end', solve(5, 5, "next"), (5, True, False))
check('next step', solve(1, 5, "next"), (2, True, True))
check('previous start', solve(1, 5, "previous"), (1, False, True))
check('previous step', solve(4, 5, "previous"), (3, True, True))
check('parameterized page count', solve(N,N+1,'next'), (N+1,True,False))
for repetition in range(N):
check('repeat previous step', solve(4, 5, "previous"), (3, True, True))
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| empty | [1, False, False] | [0, False, False] | Failed |
| shrink | [3, True, False] | [3, True, False] | Passed |
| zero | [1, False, True] | [1, False, True] | Passed |
| last | [5, True, False] | [5, True, False] | Passed |
| next end | [5, True, False] | [5, True, False] | Passed |
| next step | [2, True, True] | [2, True, True] | Passed |
| previous start | [1, False, True] | [1, False, True] | Passed |
| previous step | [3, True, True] | [3, True, True] | Passed |
| parameterized page count | [2, True, False] | [2, True, False] | Passed |
| repeat previous step | [3, True, True] | [3, True, True] | Passed |
SHA-256 / de8d9c1926dcc401b522c22a6867de6e4ab3ae552f76857ebed7bee3b0f76560
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(page, pages, action):
if pages == 0: return (0, True, True)
page = max(1, min(page, pages))
if action == 'first': page = 1
elif action == 'last': page = pages
elif action == 'next': page = min(pages, page+1)
elif action == 'previous': page = max(1, page-1)
return (page, page > 1, page < pages)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('empty', solve(1, 0, "none"), (0, False, False))
check('shrink', solve(8, 3, "none"), (3, True, False))
check('zero', solve(0, 3, "none"), (1, False, True))
check('last', solve(1, 5, "last"), (5, True, False))
check('next end', solve(5, 5, "next"), (5, True, False))
check('next step', solve(1, 5, "next"), (2, True, True))
check('previous start', solve(1, 5, "previous"), (1, False, True))
check('previous step', solve(4, 5, "previous"), (3, True, True))
check('parameterized page count', solve(N,N+1,'next'), (N+1,True,False))
for repetition in range(N):
check('repeat previous step', solve(4, 5, "previous"), (3, True, True))
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| empty | [0, True, True] | [0, False, False] | Failed |
| shrink | [3, True, False] | [3, True, False] | Passed |
| zero | [1, False, True] | [1, False, True] | Passed |
| last | [5, True, False] | [5, True, False] | Passed |
| next end | [5, True, False] | [5, True, False] | Passed |
| next step | [2, True, True] | [2, True, True] | Passed |
| previous start | [1, False, True] | [1, False, True] | Passed |
| previous step | [3, True, True] | [3, True, True] | Passed |
| parameterized page count | [2, True, False] | [2, True, False] | Passed |
| repeat previous step | [3, True, True] | [3, True, True] | Passed |
SHA-256 / 08e1804b2847b3b22f7336eec4ae5970ae153375d33574ae1770a012ef68b980
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(page, pages, action):
if pages == 0: return (0, False, False)
page = max(1, min(page, pages))
if action == 'first': page = 1
elif action == 'last': page = pages
elif action == 'next': page = min(pages, page+1)
elif action == 'previous': page = max(1, page-1)
return (page, page > 1, page < pages)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('empty', solve(1, 0, "none"), (0, False, False))
check('shrink', solve(8, 3, "none"), (3, True, False))
check('zero', solve(0, 3, "none"), (1, False, True))
check('last', solve(1, 5, "last"), (5, True, False))
check('next end', solve(5, 5, "next"), (5, True, False))
check('next step', solve(1, 5, "next"), (2, True, True))
check('previous start', solve(1, 5, "previous"), (1, False, True))
check('previous step', solve(4, 5, "previous"), (3, True, True))
check('parameterized page count', solve(N,N+1,'next'), (N+1,True,False))
for repetition in range(N):
check('repeat previous step', solve(4, 5, "previous"), (3, True, True))
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| empty | [0, False, False] | [0, False, False] | Passed |
| shrink | [3, True, False] | [3, True, False] | Passed |
| zero | [1, False, True] | [1, False, True] | Passed |
| last | [5, True, False] | [5, True, False] | Passed |
| next end | [5, True, False] | [5, True, False] | Passed |
| next step | [2, True, True] | [2, True, True] | Passed |
| previous start | [1, False, True] | [1, False, True] | Passed |
| previous step | [3, True, True] | [3, True, True] | Passed |
| parameterized page count | [2, True, False] | [2, True, False] | Passed |
| repeat previous step | [3, True, True] | [3, True, True] | Passed |
SHA-256 / b951dc12a6c5ce84698c933b420469b0337a7ae5a61b305a1f11f138fc9b3580
Verification & scope
This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:38:22.848244+00:00.
Case digest / aad413e2427db84f975b80296025d20c93bd2d2d6797701fe6f6c08fc88d5518