Skip to content

feat: support returnOnConditionCheckFailure on write operations#552

Open
anatolzak wants to merge 12 commits into
tywalch:masterfrom
anatolzak:worktree-electrodb-conditional-check-typing
Open

feat: support returnOnConditionCheckFailure on write operations#552
anatolzak wants to merge 12 commits into
tywalch:masterfrom
anatolzak:worktree-electrodb-conditional-check-typing

Conversation

@anatolzak
Copy link
Copy Markdown
Contributor

@anatolzak anatolzak commented Mar 6, 2026

closes #551

Adds a returnOnConditionCheckFailure?: boolean | "all_old" execution option for write operations (put, create, update, patch, delete, remove, upsert). When a condition expression fails, the call resolves instead of throwing.

Modes

  • true — resolves with { rejected: true }. No extra DDB cost.
  • "all_old" — resolves with { rejected: true, data: existingItem | null }. Sets DynamoDB's ReturnValuesOnConditionCheckFailure: "ALL_OLD". Requires AWS SDK v3 or v2 >= 2.1408.0.
  • false / omitted — throws (default).

Notes

  • The rejected data is typed as the full EntityItem<E> for every write op, including the update/patch chains.
  • originalErr is orthogonal — condition-check failures always resolve with { rejected: true }. originalErr only governs how non-conditional DynamoDB errors are surfaced.
  • Non-conditional DDB errors (e.g. ResourceNotFoundException) still throw normally.

Tests

  • Integration tests against DynamoDB Local on both AWS SDK v2 and v3, covering all 7 write ops for both true and "all_old" modes (84 tests).
  • tsd type-level tests for the response discriminated union, including expectError assertions for invalid string values and for result.rejected access when the option is not set.
  • Offline .params() tests verifying ReturnValuesOnConditionCheckFailure is/isn't set on the underlying DDB params.
  • Cross-cutting tests with response, data: "raw" | "includeKeys", originalErr: true.

Docs

Updated the mutation execution options reference and added a "Handling Condition Check Failures" section to mutations/conditions.

@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 6, 2026

Deploy Preview for electrodb-dev canceled.

Name Link
🔨 Latest commit 2d817fb
🔍 Latest deploy log https://app.netlify.com/projects/electrodb-dev/deploys/6a10180f69ab480008774aeb

@anatolzak
Copy link
Copy Markdown
Contributor Author

Hey @tywalch! Let me know what you think about this proposal and the API design. Handling condition check failures seems common enough that it probably deserves first class support in the library, similar to how we treat transactions today by returning errors as values.

Also sorry for the flood of PRs today 😅. While migrating to multi-attribute composite indexes, I ran into a few bugs and found some opportunities to improve the accuracy of the TypeScript types around the new feature. Appreciate you taking the time to review them!

@tywalch
Copy link
Copy Markdown
Owner

tywalch commented Mar 15, 2026

Also sorry for the flood of PRs today 😅. While migrating to multi-attribute composite indexes, I ran into a few bugs and found some opportunities to improve the accuracy of the TypeScript types around the new feature. Appreciate you taking the time to review them!

No sorry needed, your contributions have been solid and very impactful 💪 Can you give me a sense of what you're hoping for in terms of prioritization?

@anatolzak
Copy link
Copy Markdown
Contributor Author

Hey @tywalch! Do you mind taking a look at the 2 open PRs above when you get a chance?

anatolzak added 2 commits May 21, 2026 14:10
Add `returnOnConditionCheckFailure: "all_old"` option to `go()` for write
operations (put, create, update, patch, delete, remove, upsert). When a
condition expression fails, returns `{ rejected: true, data: existingItem }`
instead of throwing, using DynamoDB's `ReturnValuesOnConditionCheckFailure`.

Includes TypeScript types, integration tests (v2 + v3), params tests, and docs.
@anatolzak anatolzak force-pushed the worktree-electrodb-conditional-check-typing branch from f11ecc2 to 96df224 Compare May 21, 2026 11:11
anatolzak added 10 commits May 22, 2026 10:47
Accepts `true` in addition to `"all_old"`. The `true` mode resolves with
`{ rejected: true }` on condition failure without fetching the existing
item
— no extra DynamoDB payload cost.

`originalErr` is now orthogonal: when `returnOnConditionCheckFailure` is
set,
condition-check rejections are always caught, regardless of
`originalErr`.
Previously the two flags interacted and `originalErr: true` would
re-throw
the rejection.
…ionCheckFailure: "all_old"` is now typed as the full `EntityItem` instead of `Partial<EntityItem>`
@anatolzak
Copy link
Copy Markdown
Contributor Author

@tywalch heads up, I added another mode. On top of returnOnConditionCheckFailure: "all_old", the option now also accepts true, which returns { rejected: true } without the existing item. Useful when you only need to know the condition failed. PR body is updated.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support ReturnValuesOnConditionCheckFailure on write operations

2 participants