gastownhall/beads · error
query pagination exceeded %d pages
Error message
query pagination exceeded %d pages
What it means
QueryDataSource follows next_cursor pagination up to maxQueryPages iterations; if has_more remains true past that bound it returns this error instead of looping forever. It is a safety guard against runaway or malformed pagination from the API.
Source
Thrown at internal/notion/client.go:146
if cursor != "" {
request["start_cursor"] = cursor
}
body, err := c.doRequest(ctx, http.MethodPost, "/data_sources/"+url.PathEscape(dataSourceID)+"/query", request)
if err != nil {
return nil, err
}
var resp QueryDataSourceResponse
if err := json.Unmarshal(body, &resp); err != nil {
return nil, fmt.Errorf("parse data source query response: %w", err)
}
pages = append(pages, resp.Results...)
if !resp.HasMore || resp.NextCursor == "" {
return pages, nil
}
cursor = resp.NextCursor
}
return nil, fmt.Errorf("query pagination exceeded %d pages", maxQueryPages)
}
func (c *Client) CreatePage(ctx context.Context, dataSourceID string, properties map[string]interface{}) (*Page, error) {
request := map[string]interface{}{
"parent": map[string]interface{}{
"type": "data_source_id",
"data_source_id": dataSourceID,
},
"properties": properties,
}
body, err := c.doRequest(ctx, http.MethodPost, "/pages", request)
if err != nil {
return nil, err
}
var page Page
if err := json.Unmarshal(body, &page); err != nil {
return nil, fmt.Errorf("parse create page response: %w", err)
}View on GitHub (pinned to 71377f2769)
Solutions
- Narrow the query with a filter or smaller property set so fewer pages are needed.
- Increase the maxQueryPages constant if the data set legitimately exceeds the bound.
- Implement manual pagination yourself using resp.NextCursor with an unbounded loop and your own safety limit.
- Check for proxy caching that returns the same page repeatedly (cursor never advances).
Example fix
// before
pages, err := client.QueryDataSource(ctx, dsID, nil)
// after
pages, err := client.QueryDataSource(ctx, dsID, map[string]interface{}{
"filter": map[string]interface{}{"property": "Status", "select": {"equals": "Open"}},
"page_size": 100,
}) Defensive patterns
Strategy: validation
Validate before calling
if len(filter) == 0 {
// estimate result count first or require a filter before querying large sources
} Prevention
- Always pass a filter to QueryDataSource on large data sources
- Raise page_size (up to 100) to reduce page count
- Know your data source size before unbounded queries
- Increase maxQueryPages deliberately if you expect deep pagination
When it happens
Trigger: Calling QueryDataSource on a data source whose result set requires more pages than maxQueryPages, or a stuck cursor where the API keeps returning has_more=true with the same/next cursor indefinitely.
Common situations: Querying a very large Notion database (tens of thousands of rows) with a small page_size; a broken cursor loop caused by an API bug or by repeatedly sending the same cursor due to proxy caching.
Related errors
- Notion create database response did not include a child data
- parse current user response: %w
- parse data source response: %w
- parse database response: %w
- parse create database response: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/3e3985844bb1259f.
Report an issue: GitHub.