Skip to content

Reject pull_request_read pagination the method cannot honour - #3332

Open
sean-park-funda wants to merge 1 commit into
github:mainfrom
sean-park-funda:fix/pull-request-read-pagination-guard
Open

sean-park-funda wants to merge 1 commit into
github:mainfrom
sean-park-funda:fix/pull-request-read-pagination-guard

Conversation

@sean-park-funda

Copy link
Copy Markdown

Fixes #3316.

The problem

pull_request_read exposes two pagination mechanisms in a single schema:

  • page / perPage — get_files, get_commits, get_reviews, get_comments, get_check_runs
  • after (cursor) — get_review_comments only

When a caller passes the one the selected method does not use, the server drops it and returns results as if it were never sent. No error, no warning.

The schema description for after does say "used only by the get_review_comments method", but for a tool caller a description is guidance, not enforcement. The model sees a pagination cursor in the schema, receives a page of files, passes after to fetch the next page, gets the first page back, and has no reason to suspect anything — the call reported success with a plausible payload. The symmetric case, page on get_review_comments, is silently ignored too.

The change

A guard that runs before dispatch and returns a validation error naming the method and the parameter, in the same style as the existing unknown-method error:

method "get_files" uses page/perPage pagination; "after" is not supported
method "get_review_comments" uses cursor pagination; "page" is not supported, pass "after" instead

The pagination mechanism of each method is recorded in one map, so the whole matrix is visible in one place and a new method has to declare which mechanism it uses.

Two scoping decisions worth a look

  1. perPage is deliberately not guarded. Both mechanisms honour it, and get, get_diff and get_status are commonly called with a client's default page size. Rejecting those calls would be surprising without being useful.

  2. page on the non-paginating methods is also not guarded, for the same blanket-default reason — page: 1 is a no-op that clients send freely. after is rejected there, since nobody sends a cursor by accident. If you would rather have the stricter rule, it is a two-line change and I am happy to make it.

An unrecognised method is left alone so the dispatch switch still reports it as an unknown method rather than as a pagination problem.

Testing

  • Test_PullRequestRead_RejectsPaginationTheMethodCannotHonour — 7 cases through the handler, with a round tripper that fails the test if the GitHub API is reached, so the guard is also verified to short-circuit before the API call.
  • Test_validatePullRequestReadPagination_Accepts — 6 cases covering the combinations that must keep working, including the unknown-method passthrough.

go build ./..., go test ./... and go vet ./pkg/github/ all pass. script/generate-docs and UPDATE_TOOLSNAPS=true go test ./... produce no changes — the schema is untouched, this is a runtime guard only.

script/lint could not run cleanly in my environment: golangci-lint v2.9.0 fails to decode Go 1.27 export data on pkg/http/mark/mark.go, a file this PR does not touch. gofmt and go vet are clean.


This PR was authored by an AI agent at Vibement Inc. The diff has been read and understood before sending, and I can answer design questions about it.

pull_request_read exposes two pagination mechanisms in one schema: page/
perPage for the REST methods, and the `after` cursor for
get_review_comments. When a caller passes the one the selected method
does not use, the server drops it silently and returns the first page
again, reporting success.

The schema description says `after` is "used only by the
get_review_comments method", but for a tool caller a description is
guidance, not enforcement: it sees a cursor in the schema, receives a
page of files, passes `after` to fetch the next page, gets the first page
back, and has no signal that anything was ignored.

Validate before dispatching, in the same style as the existing unknown
method error. perPage is deliberately left unguarded, since both
mechanisms honour it and methods that do not paginate are commonly called
with a client's default page size.

Fixes github#3316

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sean-park-funda
sean-park-funda requested a review from a team as a code owner September 24, 2026 19:45
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.

pull_request_read silently ignores pagination parameters that don't apply to the selected method

1 participant