Skip to content

Cosmos: resuming a pre-fix continuation token for a feed-range-scoped cross-partition query can hard-error after upgrade #4714

Description

@simorenoh

Summary

Follow-up from PR #4705 (feed-range fan-out clip). That PR fixes cross-partition queries scoped via FeedScope::range fanning out beyond the requested range, by clipping each query-plan range to operation.target() in both the fresh and resume fan-out paths in planner.rs.

This issue tracks a second-order, cross-version interaction on the resume path that was deliberately left out of the urgent fix.

The problem

A continuation token minted by an older, pre-fix SDK for a FeedScope::range-scoped cross-partition query recorded over-scanned active_tokens — i.e. saved token ranges that lie outside the requested target (e.g. [80, FF) for a query scoped to [00, 80)).

When the fixed SDK resumes such a token:

  1. plan_resume_from_saved_snapshot clips each query-plan range to the target, so the out-of-scope portion ([80, FF)) is never resolved and contributes no coverage.
  2. The post-loop coverage check (range_fully_covered) then finds the saved [80, FF) active_tokens entry uncovered.
  3. Resume fails hard with CLIENT_CONTINUATION_TOKEN_SAVED_RANGE_UNHONORED (substatus 20213).

So a query that is mid-pagination across the upgrade boundary (token minted by old SDK, resumed by new SDK) errors instead of continuing.

Reachability / severity

  • Not purely theoretical: feed-range cross-partition queries with client-generated continuation tokens shipped in azure_data_cosmos 0.34.0 (2026-05-29) (Cosmos: add support for SELECT/WHERE on cross-partition queries using a Feed Operation Pipeline #4440), so pre-fix over-scanned tokens can exist in the wild.
  • Narrow: only affects a query resumed across the exact upgrade boundary; continuation tokens are typically short-lived within a single pagination session.
  • Fails loud: a clear error, not silent data corruption or out-of-range results.
  • The c1. continuation envelope is explicitly a preview, Rust-internal, non-stable format (see the related Finding 2 continuation-token discussion), so cross-version resume compatibility is not currently guaranteed.

Possible approach

Make the resume path tolerant of out-of-scope saved tokens: also intersect saved.active_tokens with the operation target before the coverage check, so entries entirely outside the requested range are dropped (they should not be queried anyway) rather than failing range_fully_covered. This changes resume semantics and should be designed alongside the Finding 2 continuation-token rework rather than bolted onto the urgent fix.

Care needed to distinguish:

  • "saved token is outside the requested scope" (safe to drop), from
  • "saved token is in scope but the current topology genuinely can't cover it" (must still error — real split/merge data-loss/dup risk).

Related

Pointers

  • sdk/cosmos/azure_data_cosmos_driver/src/driver/dataflow/planner.rs
    • plan_resume_from_saved_snapshot (clip applied before the coverage loop)
    • range_fully_covered and the CLIENT_CONTINUATION_TOKEN_SAVED_RANGE_UNHONORED error path

Metadata

Metadata

Assignees

No one assigned

    Labels

    CosmosThe azure_cosmos crate

    Type

    No type

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions