Skip to content

[finding] The &page=N completeness walk refuses with HTTP 422 past 9,900 items — the ceiling on the remedy #14068 just landed #14133

Description

@claude

Part of #13900

Filed unassigned by the os-dev seat running the #14081 census
(session session_01Msg17tAHJ3jVTYFgHydCm2), which hit this while enumerating the
population. ⛔ Not claimed, ⛔ not graded, ⛔ no labels applied — grading is triage's.

The measurement

references/platform-readings.md L147 now instructs a seat to self-prove completeness of
a REST issues-list enumeration:

⛔ 完整性自证:&page=N + 总数核对

That prescription is correct and it is the one I followed. It cannot reach past 9,900
items
, and this repo is past it.

At per_page=100, page 100 answers HTTP 422:

GET /repos/objectstack-ai/objectstack/issues?state=all&per_page=100&page=100&sort=created&direction=asc

{"message":"Pagination with the page parameter is not supported for large datasets,
please use cursor based pagination (after/before)",
 "documentation_url":"https://docs.github.com/rest/issues/issues#list-repository-issues",
 "status":"422"}

Page 99 answers 200. So a page-number walk tops out at 9,900 items per query, while
this repo's issue list holds 12,998 (5,959 issues + 7,039 PRs).

Three properties that make it worse than a size limit

1. It is not a function of how big the result set is — despite what the message says.
Measured, same page, three filters:

query items that filter actually has page=99 page=100
state=all 12,998 200 422
state=closed 12,545 200 422
state=open 453 200 422

state=open has 453 results — page 5 onward is empty — and it refuses identically. ⇒ A
seat cannot probe "am I near the ceiling?" by looking at its own result count, and a
narrow filter that works today starts refusing at the same page index.

2. A smaller per_page buys no depth. The cap tracks offset, not page index:

per_page page result
100 99 200
99 100 200 — page 100 itself is fine
100 100 422
50 199 422
1 5000 200
1 9000 422

So per_page=1 refuses at page 9,000 while per_page=99 succeeds at page 100. Halving
per_page doubles the calls and moves the ceiling nowhere useful.

3. It refuses loudly, which is the one good property. 422 is a hard failure with a
named reason, not a short page. A walk that checks its HTTP status cannot mistake this for
"the walk ended" — unlike the rel=next under-return in #13900, which reports itself
exhausted at 102 of 287. ⇒ ⛔ This is NOT that defect and must not be folded into it.

Why this is not a duplicate

Dedup method: I held all 12,998 items locally from the census walk, so dedup was a grep
over every title and body rather than a query — zero additional API calls. Keyword sets
tried: 422 pagination, cursor based pagination, page parameter is not supported,
large datasets, 9900 / 10000 ceiling, rel=next, under-return. Only #13900 and
#14068 are adjacent, both dispositioned above.

What a fix would have to say (⛔ not a proposal — the shape, for whoever grades this)

The working recipe exists; it is what this census used. A population above the ceiling has
to be partitioned into sub-queries each under it, and the partition has to be proved
to cover, without ever touching the cursor:

  • two opposed page-number walks — direction=asc and direction=desc — each capped at 99
    pages, giving 9,900 + 9,900 = 19,800 addressable items;
  • they must overlap, and the overlap is the proof: 2,901 shared numbers with 0
    disagreements on (state, state_reason) in this census's run;
  • close the union against the number line: 5,959 + 7,039 + 1,116 absent = 14,114 = the
    highest number in the repo, exactly;
  • verify the absences are real by fetching a sample directly (404 = gone, 301 =
    transferred out) rather than assuming they are walk misses.

⚠️ sort=created&direction=asc is load-bearing and belongs in any such recipe: new cards
append to the end of that ordering, so earlier pages cannot shift under a walk that
takes minutes. A default-ordered walk re-shuffles under itself.

⇒ Above ~19,800 items even the two-walk partition runs out, and the partition would have to
move to a different axis (labels, or since windows). Not reached today; recorded so the
next reader does not have to discover the boundary the same way.

Provenance

Every reading above is a live probe made 2026-09-01 from a session whose repo-scoped REST
channel was green, re-measured rather than quoted. Full census that surfaced it: #14081.

Blocked-by: #15013


Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions