Skip to content

Fix KeyError: 'version' in SessionContainer.get_session_token#47798

Merged
ausfeldt merged 9 commits into
Azure:mainfrom
ausfeldt:users/gaausfel/fix-session-version
Jul 10, 2026
Merged

Fix KeyError: 'version' in SessionContainer.get_session_token#47798
ausfeldt merged 9 commits into
Azure:mainfrom
ausfeldt:users/gaausfel/fix-session-version

Conversation

@ausfeldt

@ausfeldt ausfeldt commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Description

The service-returned "partitionKey" definition does not always include the optional version field. When it does not, "collection_pk_definition['version']" raises "KeyError", which the surrounding "except (KeyError, AttributeError)" silently swallows. The function returns`"" and the client omits the "x-ms-session-token" header on the next read. Against the Dedicated Gateway / Integrated Cache, every Session-consistency read is then rejected as "CacheMiss" even against a warm cache for the same document.

Two-line change in sdk/cosmos/azure-cosmos/azure/cosmos/_session.py (sync at line 122 and async at line 216):
"version=collection_pk_definition['version']" to "version=collection_pk_definition.get('version')".

"PartitionKey" already accepts "version=None" and defaults to V2 internally, so the semantic behavior is unchanged when "version" is present.

All SDK Contribution checklist:

  • The pull request does not introduce [breaking changes]
  • CHANGELOG is updated for new features, bug fixes or other significant changes.
  • I have read the contribution guidelines.

General Guidelines and Best Practices

  • Title of the pull request is clear and informative.
  • There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, see this page.

Testing Guidelines

  • Pull request includes test coverage for the included changes.

REDMOND\gaausfel and others added 2 commits June 29, 2026 15:54
The sync and async `SessionContainer.get_session_token` accessed
`collection_pk_definition['version']` with bracket notation. When the
service-returned `partitionKey` payload omits the optional `version`
field (common for containers created without an explicit V2 partition
key), this raised `KeyError`, which was silently swallowed by the
surrounding `except (KeyError, AttributeError)`.

The net effect was that `get_session_token` returned an empty string,
so the client sent no `x-ms-session-token` header on the next read.
Against the Dedicated Gateway / Integrated Cache, every
Session-consistency read was rejected as a cache miss (verified at the
server with `ComputeRequest5M.CacheHitLevel`: 695 reads / 0
CacheFullHit pre-fix vs 678 reads / 677 CacheFullHit post-fix on the
same item).

Treating `version` as optional and passing `None` to `PartitionKey`
when it is missing matches the existing `PartitionKey` constructor
contract and restores Session-consistency cache hits.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Covers SessionContainer.get_session_token in tests/test_session_token_unit.py:

  test_partitionkey_definition_without_version_returns_token
      Mirrors the live failure: container_properties_cache holds a
      partitionKey definition without 'version' (as the service returns it
      for containers created without explicit V2 partition-key versioning).
      Asserts a real per-partition token is returned (was '' before the
      fix, because the KeyError was silently swallowed).

  test_partitionkey_definition_with_version_returns_same_token
      Pins the no-regression case: when 'version' IS present, behavior is
      unchanged.

Verified by reverting the fix locally and observing that the without_version
test fails with AssertionError: '' != '0:1#100'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 1, 2026 21:00
@ausfeldt ausfeldt requested a review from a team as a code owner July 1, 2026 21:00
@github-actions github-actions Bot added the Cosmos label Jul 1, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR intends to fix a KeyError: 'version' in SessionContainer.get_session_token (sync and async) that occurs when the service-returned partitionKey definition omits the optional version field. The KeyError was being silently swallowed by a broad except, causing the client to omit the x-ms-session-token header on subsequent reads and turning every Session-consistency read against the Dedicated Gateway / Integrated Cache into a cache miss. The change replaces collection_pk_definition['version'] with collection_pk_definition.get('version') in both code paths, plus a CHANGELOG entry and new unit tests.

Changes:

  • Use .get('version') instead of ['version'] when constructing PartitionKey in the sync and async get_session_token paths.
  • Add a CHANGELOG.md bug-fix entry.
  • Add unit tests covering the missing/present partitionKey.version cases for the sync path.

Key concern: The chosen fix avoids the KeyError but does not correctly restore behavior. Passing version=None (what .get('version') returns when the key is missing) is not the same as omitting the keyword: PartitionKey.__init__ only applies its V2 default when version is absent, so None is stored and the effective-partition-key hashing falls through to a non-hash encoding, producing an incorrect EPK. A concrete default (e.g. 1, matching the existing _get_partition_key_from_partition_key_definition helper) is needed. The new tests don't catch this because the routing-map stub ignores the computed EPK.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
sdk/cosmos/azure-cosmos/azure/cosmos/_session.py Changes version=collection_pk_definition['version'] to .get('version') in sync (L122) and async (L216) paths; avoids KeyError but passes None, yielding an incorrect EPK instead of the V2 default.
sdk/cosmos/azure-cosmos/tests/test_session_token_unit.py Adds sync-only tests for missing/present partitionKey.version; the routing-map stub discards the computed EPK ranges, so it doesn't validate the fix's core resolution behavior.
sdk/cosmos/azure-cosmos/CHANGELOG.md Adds bug-fix entry; wording ("defaults to None, matching how PartitionKey handles a missing version") is inaccurate.

Comment thread sdk/cosmos/azure-cosmos/azure/cosmos/_session.py Outdated
Comment thread sdk/cosmos/azure-cosmos/azure/cosmos/_session.py Outdated
Comment thread sdk/cosmos/azure-cosmos/tests/test_session_token_unit.py
Comment thread sdk/cosmos/azure-cosmos/CHANGELOG.md Outdated

@NaluTripician NaluTripician left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the thorough root-cause writeup — the diagnosis (swallowed KeyError -> empty session token -> Integrated Cache misses against the Dedicated Gateway) is spot-on and worth fixing.

I did dig into the actual partition_key.py code paths, though, and I think the fix as written trades the loud failure for a quieter correctness bug. The premise in the description — "PartitionKey accepts version=None and defaults to V2 internally" — doesn't hold: passing version=None explicitly keeps self.version = None, and for a Hash container that falls through _get_hashed_partition_key_string to the raw-binary EPK path rather than V1/V2 hashing. It's harmless on single-partition containers (which the new tests cover) but can target the wrong partition — or produce an empty token — on multi-partition Hash containers.

The one-line change to .get('version', 1) (matching the existing _get_partition_key_from_partition_key_definition convention), plus a test that exercises real EPK->range resolution, should make this solid. Details inline. Defaulting to 1 also matches .NET/Java (absent version => V1 for legacy containers), whereas None is a Python-only divergence.

Comment thread sdk/cosmos/azure-cosmos/azure/cosmos/_session.py Outdated
Comment thread sdk/cosmos/azure-cosmos/azure/cosmos/_session.py Outdated
Comment thread sdk/cosmos/azure-cosmos/CHANGELOG.md Outdated
Comment thread sdk/cosmos/azure-cosmos/tests/test_session_token_unit.py Outdated
Comment thread sdk/cosmos/azure-cosmos/CHANGELOG.md Outdated
FabianMeiswinkel and others added 2 commits July 2, 2026 00:52
Co-authored-by: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com>
Updated the default value of `partitionKey.version` to 1 in `SessionContainer.get_session_token` to match `PartitionKey` behavior.

@FabianMeiswinkel FabianMeiswinkel left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

The prior tests used a routing-map stub that discarded the ranges
argument and returned a fixed partition range regardless of the
computed effective partition key, so a wrong-EPK regression (e.g.
version=None falling through to the raw-binary encoding) would still
have passed the assertions on the returned session token.

Replace the stub with a capturing variant that records what
get_overlapping_ranges received, and add two tests:

  test_missing_version_produces_v1_hash_epk_not_raw_binary
      Computes the V1-hash EPK independently and asserts the captured
      EPK matches. Fails if the fix ever regresses to
      version=None (the actual EPK would be the raw-binary encoding).

  test_v1_and_v2_produce_different_epks
      Sanity check: V1 and V2 must produce distinct EPKs, otherwise
      the V1-EPK assertion above becomes vacuous.

Verified by temporarily reverting to .get('version') (no default) and
observing the new EPK test fails with AssertionError comparing the
raw-binary encoding against the expected V1 hash.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread sdk/cosmos/azure-cosmos/CHANGELOG.md Outdated
Comment thread sdk/cosmos/azure-cosmos/CHANGELOG.md Outdated
FabianMeiswinkel and others added 2 commits July 7, 2026 18:56
Co-authored-by: Simon Moreno <30335873+simorenoh@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
REDMOND\gaausfel and others added 2 commits July 9, 2026 07:51
@simorenoh

Copy link
Copy Markdown
Member

/check-enforcer override

@simorenoh

Copy link
Copy Markdown
Member

@microsoft-github-policy-service rerun

@simorenoh simorenoh closed this Jul 10, 2026
@simorenoh simorenoh reopened this Jul 10, 2026
@ausfeldt ausfeldt merged commit 0ccf783 into Azure:main Jul 10, 2026
31 of 41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

6 participants