Skip to content

Conversation

@RanVaknin
Copy link
Contributor

@RanVaknin RanVaknin commented Jan 6, 2026

Fixes: #6435

Background

In July 2024, PR #6019 introduced custom versioning support for VersionedRecordExtension, allowing developers to configure startAt and incrementBy values. However, it left two critical gaps: (1) SDK v1 → v2 migration was blocked for tables containing records with version=0, as the SDK threw ConditionalCheckFailedException when updating these records, and (2) new records still couldn't start at version 0, they always started at startAt + incrementBy (e.g., default config produced version 1, not 0). This PR addresses both issues.

The bugs and the fixes

Issue 1: v1 Existing Records with version 0 can't be updated

Users migrating from v1 to v2 cannot update existing records that were created with version=0. v1 allowed records with version=0, but when these records are retrieved via v2's GetItem and then updated via UpdateItem, the operation fails with ConditionalCheckFailedException. This occurs because the SDK cannot distinguish between:
• A new record where the user explicitly set a certain version (was covered)
• An existing record retrieved from DynamoDB that happens to have that same version (was not covered)

Solution:

Since the client code cannot distinguish between these two states, a way we can disambiguate this is by pushing the logic to the DDB server with an OR condition:

if (suppliedVersion == record.version) {
    condition = "attribute_not_exists(version) OR version = :val";
}

How it works:
New records: attribute_not_exists(version) → TRUE, operation succeeds
Existing records: version = startAt → TRUE, operation succeeds

Issue 2: New Records Cannot Start at 0

Even after PR #6019 introduced custom versioning configuration, new records still cannot start at version 0. With the default configuration (startAt=0, incrementBy=1), the first version assigned to a new record is 1, not 0. This is because the initial version calculation uses startAt + incrementBy, meaning startAt doesn't actually control where versions begin—it's an offset that gets added to incrementBy.

Solution:

Remove validation blocking negative startAt values. This allows users to set startAt=-1, which produces the desired result:
• First version: -1 + 1 = 0
• Subsequent versions: 1, 2, 3...

VersionedRecordExtension.builder()
    .startAt(-1L)
    .incrementBy(1L)
    .build();
// First version: -1 + 1 = 0

Add support for handling existing records with version 0
added ability to set startAt to -1 to allow versioning to begin from 0
@RanVaknin RanVaknin requested a review from a team as a code owner January 6, 2026 06:24
@RanVaknin RanVaknin added the no-api-surface-area-change Indicate there is no API surface area change and thus API surface area review is not required label Jan 6, 2026
"type": "bugfix",
"category": "DynamoDB Enhanced Client",
"contributor": "",
"description": "Allow new records to start at version=0 by supporting startAt=-1 in VersionedRecordExtension"
Copy link
Contributor

Choose a reason for hiding this comment

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

Its a little weird to say use startAt=-1 for records to start at 0.... what about using "initialize" instead? like - "Allow new records to be initialized with version=0 by setting startAt=-1"? or something like that

@sonarqubecloud
Copy link

sonarqubecloud bot commented Jan 8, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-api-surface-area-change Indicate there is no API surface area change and thus API surface area review is not required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DynamoDB Enhanced Client Custom Versioning startAt parameter does not appear to work when setting to 0

3 participants