gastownhall/beads · error
pagination limit exceeded: stopped after %d pages
Error message
pagination limit exceeded: stopped after %d pages
What it means
FetchIssues pages through Linear issues cursor-style and hard-stops after MaxPages pages to prevent unbounded loops, returning this error and discarding all accumulated issues. It means the result set (paginated at MaxPageSize per page) exceeded the maximum page budget.
Source
Thrown at internal/linear/client.go:488
case "closed":
filter["state"] = map[string]interface{}{
"type": map[string]interface{}{
"in": []string{"completed", "canceled"},
},
}
}
page := 0
for {
select {
case <-ctx.Done():
return allIssues, ctx.Err()
default:
}
page++
if page > MaxPages {
return nil, fmt.Errorf("pagination limit exceeded: stopped after %d pages", MaxPages)
}
variables := map[string]interface{}{
"filter": filter,
"first": MaxPageSize,
}
if cursor != "" {
variables["after"] = cursor
}
req := &GraphQLRequest{
Query: issuesQuery,
Variables: variables,
}
data, err := c.Execute(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to fetch issues: %w", err)View on GitHub (pinned to 71377f2769)
Solutions
- Use FetchIssuesSince with the last sync timestamp instead of a full FetchIssues scan
- Narrow the query by setting Client.ProjectID or a tighter state filter
- Raise MaxPages (and possibly MaxPageSize) constants if the budget is genuinely too small
- Split the sync by project or by time window so each run stays under the page budget
Example fix
// before: full scan every run issues, err := client.FetchIssues(ctx, "all") // after: incremental sync client := linear.NewClient(token, teamID, "") issues, err := client.FetchIssuesSince(ctx, "all", lastSyncTime)
Defensive patterns
Strategy: fallback
Validate before calling
// Estimate the result size before a full fetch
recent, err := client.FetchIssuesSince(ctx, state, time.Now().Add(-24*time.Hour))
if err != nil && strings.Contains(err.Error(), "pagination limit exceeded") {
return errors.New("dataset too large for a single FetchIssues run; use incremental sync")
} Prevention
- Prefer FetchIssuesSince with a persisted watermark over full scans
- Set Client.ProjectID to narrow the result set
- Raise MaxPages deliberately if the team genuinely has more data
- Chunk initial backfill by time windows or by project
- Alert when the page budget is hit so syncs don't silently drop data
When it happens
Trigger: Calling FetchIssues(ctx, state) where the number of issues matching the filter (team, optional project, optional open/closed state) exceeds MaxPages × MaxPageSize — e.g. a team with thousands of open issues fetched with state="open" or "all".
Common situations: Large teams with heavy issue history running a full (non-incremental) sync; a project ID filter that no longer narrows results; state="all" pulls on backlogged teams.
Related errors
- missing external ref for Linear issue %s
- Linear project milestone is missing id
- generating Linear milestone epic ID: %w
- creating Linear milestone epic %q: %w
- searching local issues for Linear milestone %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/01d0335a49c58614.
Report an issue: GitHub.