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

  1. Narrow the query with a filter or smaller property set so fewer pages are needed.
  2. Increase the maxQueryPages constant if the data set legitimately exceeds the bound.
  3. Implement manual pagination yourself using resp.NextCursor with an unbounded loop and your own safety limit.
  4. 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

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/3e3985844bb1259f. Report an issue: GitHub.