Skip to content

fix(idempotency): return stored falsy responses on replay - #8701

Open
thebadalov wants to merge 1 commit into
aws-powertools:developfrom
thebadalov:fix/idempotency-falsy-response-replay
Open

thebadalov wants to merge 1 commit into
aws-powertools:developfrom
thebadalov:fix/idempotency-falsy-response-replay

Conversation

@thebadalov

Copy link
Copy Markdown

Issue number: closes #8700

Summary

Changes

IdempotencyHandler._handle_for_status now checks response_dict is not None before deserializing the stored response, the same check _get_function_response already uses when saving it.

Added test_idempotent_function_falsy_response_replay, parametrized over 0, False, "", [] and {}. Each case calls the function twice with the same payload and checks that the second call returns the same value and type without running the function again. All five cases fail on the current develop and pass with the fix.

User experience

  • Before: a function returning 0, False, "", [] or {} got None back on every replay.
  • After: the replay returns the stored value. Functions that return None and truthy values behave the same as before.

Testing

  • tests/functional/idempotency and tests/unit/idempotency: 207 passed
  • ruff format, ruff lint, mypy and ty: clean
  • Checked against a local Redis server with CachePersistenceLayer for 0, False, "", [], {}, None and a truthy value

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

_handle_for_status only deserialized the stored response when it was
truthy, so a function returning 0, False, "", [] or {} got None back on
every replay, even though the value was saved correctly.

Check for None instead, matching the write path in
_get_function_response.
@thebadalov
thebadalov requested a review from a team as a code owner October 29, 2026 13:22
@boring-cyborg boring-cyborg Bot added the tests label Oct 29, 2026
@powertools-for-aws-oss-automation powertools-for-aws-oss-automation Bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Oct 29, 2026
@sonarqubecloud

Copy link
Copy Markdown

@leandrodamascena leandrodamascena 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 @thebadalov, confirmed against real DynamoDB and Valkey: on develop every falsy return (0, False, "", [], {}) comes back as None on replay, with your change each one comes back as the stored value with the right type, and None and truthy values are unchanged. The dataclass serializer path is fine too.

I'm approving now. This goes out in 3.40.0, so it will sit here for a while before I merge it. No rebase needed in the meantime, and you'll be credited in the release notes.

This branch has not been deployed

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

Labels

size/M Denotes a PR that changes 30-99 lines, ignoring generated files. tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: idempotent functions return None on replay when the stored response is falsy (0, False, "", [], {})

2 participants