Skip to content

Conversation

@bentsku
Copy link
Contributor

@bentsku bentsku commented Sep 23, 2025

Motivation

Follow up from #13180

When working on multi-protocol support, it came to light that we shouldn't serialize empty members on exception structures. However, one test started failing for the verifiedpermissions service after we merged this.

This is because the shape of that exception explicitly declares required members on the exception structure shape:

{
  "ResourceNotFoundException":{
      "type":"structure",
      "required":[
        "message",
        "resourceId",
        "resourceType"
      ],
      "members":{
        "message":{"shape":"String"},
        "resourceId":{
          "shape":"String",
          "documentation":"<p>The unique ID of the resource referenced in the failed request.</p>"
        },
        "resourceType":{
          "shape":"ResourceType",
          "documentation":"<p>The resource type of the resource referenced in the failed request.</p>"
        }
      },
      "documentation":"<p>The request failed because it references a resource that doesn't exist.</p>",
      "exception":true
    }
}

I've added unit tests to validate the fix and confirm the behavior, and validated that it fixed the test of the dependency.

Changes

  • fix behavior when serializing exception members to take into account required non-truthy values members
    • validate that the None value is still not serialized
  • also validated the fix for smithy-rpc-v2-cbor even though we don't have a service supporting required members yet

@bentsku bentsku added this to the 4.9 milestone Sep 23, 2025
@bentsku bentsku added area: asf semver: patch Non-breaking changes which can be included in patch releases docs: skip Pull request does not require documentation changes review: merge when ready Signals to the reviewer that a PR can be merged if accepted labels Sep 23, 2025
@github-actions
Copy link

github-actions bot commented Sep 23, 2025

S3 Image Test Results (AMD64 / ARM64)

    2 files  ±0    2 suites  ±0   8m 13s ⏱️ +9s
  532 tests ±0  480 ✅ ±0   52 💤 ±0  0 ❌ ±0 
1 064 runs  ±0  960 ✅ ±0  104 💤 ±0  0 ❌ ±0 

Results for commit c3cb5ca. ± Comparison against base commit 692af03.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Sep 23, 2025

Test Results - Preflight, Unit

22 269 tests  +10   20 528 ✅ +10   15m 30s ⏱️ -36s
     1 suites ± 0    1 741 💤 ± 0 
     1 files   ± 0        0 ❌ ± 0 

Results for commit c3cb5ca. ± Comparison against base commit 692af03.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Sep 23, 2025

Test Results (amd64) - Acceptance

7 tests  ±0   5 ✅ ±0   3m 26s ⏱️ +9s
1 suites ±0   2 💤 ±0 
1 files   ±0   0 ❌ ±0 

Results for commit c3cb5ca. ± Comparison against base commit 692af03.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Sep 23, 2025

Test Results (amd64) - Integration, Bootstrap

    5 files  ±0      5 suites  ±0   2h 37m 2s ⏱️ -59s
5 155 tests ±0  4 659 ✅ ±0  496 💤 ±0  0 ❌ ±0 
5 161 runs  ±0  4 659 ✅ ±0  502 💤 ±0  0 ❌ ±0 

Results for commit c3cb5ca. ± Comparison against base commit 692af03.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Sep 23, 2025

LocalStack Community integration with Pro

    2 files  ±0      2 suites  ±0   1h 58m 59s ⏱️ + 1m 30s
4 781 tests ±0  4 445 ✅ ±0  336 💤 ±0  0 ❌ ±0 
4 783 runs  ±0  4 445 ✅ ±0  338 💤 ±0  0 ❌ ±0 

Results for commit c3cb5ca. ± Comparison against base commit 692af03.

♻️ This comment has been updated with latest results.

continue

if value:
if value or (member in shape.required_members and value is not None):
Copy link
Member

Choose a reason for hiding this comment

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

Just chiming in here, even though the PR is not ready for review yet: As far as I can see, this would nearly be semantically equal to:

                if value is not None:

The only case that would slip though here (and wouldn't in your solution) is that a falsy non-required value would also be serialized.
My question is: Is that really the differentiation? That looks a bit weird to me 😅 If so, please add a comment to this section 🤣

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is exactly what it means 😅 any non-truthy values will not be serialized (this might be problematic with numbers values, but we haven't encountered it yet in an exception structure). I added more unit tests to illustrate this.

For example, if you instantiate a ServiceException-derived exception, the exception message field is set to "", so it illustrated the falsy value thing.

Copy link
Member

Choose a reason for hiding this comment

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

Okay, right 😅 Might be good to explain this in a comment, as this is a bit specific and hard to read. 😛

Copy link
Contributor Author

@bentsku bentsku Sep 24, 2025

Choose a reason for hiding this comment

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

I think I'll update the logic to be in 2 steps to be clearer, and add comments 😄:

if value is None:
    continue

if value or member in shape.required_members:
    remaining_params[member] = value

Copy link
Contributor Author

@bentsku bentsku Sep 24, 2025

Choose a reason for hiding this comment

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

As a side-note, while working on the backup service which is a rest-json service, I noticed that it returns null values exception members in the raw body 😅 (but Botocore does not deserialize them) so I think the logic is different there, and is not entirely derived from our JSONResponseSerializer. I'll investigate a bit later! For boto3, this is not an issue as it does not deserialize null fields back to the user.

@bentsku bentsku force-pushed the asf-fix-required-exception-members branch from aa9383f to 18d1256 Compare September 24, 2025 08:34
@bentsku bentsku marked this pull request as ready for review September 24, 2025 08:35
@bentsku bentsku requested a review from thrau as a code owner September 24, 2025 08:35
Copy link
Member

@alexrashed alexrashed left a comment

Choose a reason for hiding this comment

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

Really good catch and great tests! 🐛🔨

continue

if value:
if value or (member in shape.required_members and value is not None):
Copy link
Member

Choose a reason for hiding this comment

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

Okay, right 😅 Might be good to explain this in a comment, as this is a bit specific and hard to read. 😛

@bentsku bentsku merged commit f7ffe66 into main Sep 24, 2025
48 checks passed
@bentsku bentsku deleted the asf-fix-required-exception-members branch September 24, 2025 10:37
@alexrashed alexrashed added the notes: skip Pull request does not have to be mentioned in the release notes label Sep 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: asf docs: skip Pull request does not require documentation changes notes: skip Pull request does not have to be mentioned in the release notes review: merge when ready Signals to the reviewer that a PR can be merged if accepted semver: patch Non-breaking changes which can be included in patch releases

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants