Skip to content

Pagination iterator mishandles server-side-filtered dataset pages #979

Description

@vdusek

DatasetClient.listItems() used as an async iterable returns wrong results with clean / skipEmpty / skipHidden.

The API applies offset/limit to the raw item stream and filters afterwards, so a page can scan up to limit rows while returning fewer (or zero) items. x-apify-pagination-count reports the scanned window; the iterator ignores it. Two bugs in _listPaginatedFromCallback:

  1. Stops earlyitems.length > 0 (src/base/api_client.ts:118) ends iteration on a fully filtered page, even though later pages hold matching items.
  2. Yields duplicatescurrentOffset += currentPage.items.length (src/base/api_client.ts:128) advances by returned instead of scanned items, so the next page re-scans rows already yielded. The header is discarded at src/resource_clients/dataset.ts:400.

Cursor iterators (listKeys, listRequests, paginateRequests) are unaffected — the API never returns an empty page with a usable cursor.

Fixed in the Python client in apify/apify-client-python#964. A JS fix must read x-apify-pagination-count separately for bookkeeping, since count in PaginatedList is public and intentionally set to data.length.

API-side root cause: apify/apify-core#27324.

✍️ Drafted by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working.t-toolingIssues with this label are in the ownership of the tooling team.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions