Skip to content

Parse modeled members from AWS JSON errors - #3

Open
ikolomiets wants to merge 2 commits into
cloudboss:mainfrom
ikolomiets:agent/parse-modeled-aws-json-errors
Open

Parse modeled members from AWS JSON errors#3
ikolomiets wants to merge 2 commits into
cloudboss:mainfrom
ikolomiets:agent/parse-modeled-aws-json-errors

Conversation

@ikolomiets

@ikolomiets ikolomiets commented Aug 4, 2026

Copy link
Copy Markdown

Disclaimer: The Issue and PR were created using Codex gpt-5.6-sol xhigh.

Fixes #2

Problem

DynamoDB supports ReturnValuesOnConditionCheckFailure=ALL_OLD for conditional writes. This lets callers retrieve the item that caused a failed condition directly from ConditionalCheckFailedException, which is useful for optimistic concurrency and conflict resolution based on a stored hash.

The generated SDK already supports sending the request option:

.return_values_on_condition_check_failure = .all_old

The pinned AWS model also defines ConditionalCheckFailedException.Item as an AttributeMap. The missing capability was response handling:

  • Generated exception structs contained only the normalized message and synthetic request_id fields.
  • AwsJsonProtocol identified the error code but constructed the exception without deserializing the response body.
  • Consequently, DynamoDB returned the old item, but the SDK discarded it before exposing the diagnostic.
  • Callers received error.ServiceError and the correct .conditional_check_failed_exception diagnostic variant, but could not access the returned item or its hash.
  • ReturnValues=ALL_OLD is not a substitute: it applies to successful writes, while conditional failures require ReturnValuesOnConditionCheckFailure.

This is a generic AWS JSON generator defect rather than a DynamoDB-only omission. Every modeled exception member beyond message and request_id was discarded for AWS JSON 1.0/1.1 services, including other structured diagnostic fields such as cancellation and throttling details.

Fix

  • Add a protocol capability indicating that AWS JSON protocols parse modeled error bodies, while leaving REST JSON/XML and Query protocols unchanged.
  • Extend AWS JSON 1.0/1.1 error generation to emit:
    • Modeled exception members and documentation.
    • Resolved Zig types with output-style optionality and defaults.
    • Imports for referenced structures, enums, unions, lists, and map values.
    • aws.map.MapEntry support for maps, including maps nested through lists.
    • json_field_names mappings that preserve Smithy wire casing.
  • Preserve the existing normalized message and request_id fields and reserve those normalized names to avoid duplicate fields.
  • Deserialize recognized error response bodies with aws.json.parseJsonObject into the generated exception type, allocating from the diagnostic arena.
  • Overwrite parsed message and request metadata with the SDK's normalized values to preserve current behavior.
  • Keep the existing .unknown diagnostic fallback, including code, message, and HTTP status, when a recognized error body is malformed.
  • Propagate OutOfMemory rather than converting allocation failure into an unknown service error.
  • Add generator coverage for AWS JSON 1.0 and 1.1 and a DynamoDB LocalStack regression covering both the absent and .all_old cases.
  • Regenerate every affected AWS JSON service from the pinned models.

The additive DynamoDB API is:

dynamodb.errors.ConditionalCheckFailedException.item:
    ?[]const aws.map.MapEntry(AttributeValue)

Typical access remains through the diagnostic union:

switch (diagnostic.kind) {
    .conditional_check_failed_exception => |failure| {
        const old_item = failure.item;
    },
    else => {},
}

The returned data is owned by ServiceError's arena and remains valid until diagnostic.deinit().

Why so many generated Zig files change

The handwritten fix is protocol-wide, not operation-specific. AWS JSON error parsing is generated into each operation module, so changing the recognized-error dispatch and importing typed error structures updates every generated operation for an AWS JSON service. Each service's errors.zig also changes because modeled exception members, supporting imports, documentation, defaults, and JSON wire-name mappings are now emitted.

As a result, the regeneration commit contains 6,863 generated files across 152 AWS JSON 1.0/1.1 services. The large diff is the complete deterministic output of one generic generator change against the repository's pinned AWS models; it is not 6,863 independently handwritten changes. Keeping the full regeneration ensures that every affected service exposes its modeled error payload consistently and that checked-in generated sources match the generator.

The generated output is isolated in its own commit so reviewers can examine the six handwritten/test files independently from the mechanical regeneration.

Compatibility

  • Existing ServiceError, operation return types, normalized messages, request IDs, retry behavior, and unknown-error handling remain compatible.
  • The change is additive for consumers: AWS JSON exception structs now expose modeled members.
  • REST JSON/XML and Query protocols retain their current behavior.
  • Updating downstream SDK pins and consuming the returned DynamoDB hash are separate follow-up changes.

Validation

Previously completed before PR preparation:

  • make codegen-dynamodb
  • make codegen
  • make test — 413 tests plus generated service compilation
  • make test-integration-localstack SCENARIO=dynamodb — 19/19 tests
  • git diff --check

@ikolomiets
ikolomiets marked this pull request as ready for review August 4, 2026 04:43
@rjosephwright

Copy link
Copy Markdown
Contributor

Hi @ikolomiets,

Thanks for the PR.

I'd prefer try parseErrorResponse(...) over parseErrorResponse(...) catch return error.OutOfMemory.

The parseErrorResponse function has grown quite large and is duplicated in each service operation. The code generator should put this into errors.zig for each service where it can be reused.

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.

AWS JSON errors discard modeled response members

2 participants