All packsOffline Sync EngineSolve
sync cursor expired 410 fallback full resync
A cursor older than the compaction window can't just resume
A client that's been offline longer than the tombstone retention window holds a cursor into data the server has already compacted away -- it has to reset, not resume.
What goes wrong
The server periodically compacts old tombstones to keep storage bounded, which means a client that's been disconnected long enough can hold a pull cursor pointing at data that no longer exists in the form it expects. Naively resuming from that stale cursor either serves incomplete data (silently missing everything that was compacted) or errors in a way the client has no built-in recovery path for.
Why agents get it wrong
Pagination cursors are normally assumed to remain valid indefinitely -- "just resume from where you left off" is the standard mental model for any paginated API, and most systems don't compact the underlying data out from under a cursor. Building both the compaction routine and a cursor whose validity depends on it requires connecting two features (storage cleanup and sync resumption) that don't obviously interact until you specifically ask what happens to an old cursor after a compaction runs.
What Offline Sync Engine pre-decides
The server tracks a min_safe_cursor watermark that only ever advances, set by compactTombstones() to the highest sequence number it actually purged. A pull with a cursor older than that watermark fails explicitly with 410 cursor_expired, and the client's documented response is a full reset: clear local cells, cursor back to zero, pull everything, then re-apply its own outbox on top so queued local edits survive the reset. Cursor 0 is always legal, which is what makes the reset path safe rather than a dead end.
Source: ARCHITECTURE.md 'Pagination (decided)' and 'Deletes and tombstones (decided)'