## TL;DR

Query locators expire after about 15 minutes of inactivity, so a slow consumer loses its place mid-export. Page briskly without long pauses between requests, and if the export is large, use a Bulk API query job instead of the locator pattern. On expiry, re-issue the query; the data is still there.

## Error

```text
INVALID_QUERY_LOCATOR: invalid query locator
```

## Steps

1. On expiry, re-issue the original query to get a fresh locator and restart paging from the top, skipping already-processed ids. Expected: the export continues.
2. Remove pauses between page requests: no per-page enrichment, no sleeps, no slow writes. Expected: the locator stays alive.
3. Reduce the page size if each page is slow to transfer, or increase it if round trips dominate. Expected: the sweet spot keeps the locator fed.
4. For exports over a few hundred thousand rows, switch to a Bulk API query job. Expected: no locator to expire.
5. Track processed ids so a restart never double-processes. Expected: idempotent resume.

## When to use

- Exports fail with INVALID_QUERY_LOCATOR partway.
- An agent enriches each page before fetching the next (too slow).
- Large exports that take longer than 15 minutes.

## When not to use

- Bulk API job failures (different mechanics).
- Query syntax errors (fix the SOQL).

## Tool compatibility

- Salesforce SOAP and REST query/queryMore with locators.
- Bulk API query jobs as the alternative.

## Variant phrasings

### invalid query locator

Re-issue and page faster.

### queryMore failed mid-export

Same expiry; same fix.

## Why it happens

The locator is a server-side cursor with a short idle timeout. Anything that pauses paging (slow processing, rate-limit sleeps, crashes) lets it expire.

## Edge cases

- Re-issuing the query can return rows in a different order; dedupe by id.
- Very selective queries re-run fast; unselective full-table queries are slow to restart, favor Bulk API.
- Parallel paging with multiple locators multiplies server load; keep it modest.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_WIZJ8JhUNw8uWBx_b2qVpQ
