Skip to content

Conversation

@AndrewAsseily
Copy link
Contributor

@AndrewAsseily AndrewAsseily commented Dec 2, 2025

Issue

CLI-5136 & CLI-7572 & #2688

Description of changes

Exposes modeled error members from AWS service exceptions in the configured output format. This lets users access service-specific error details.

The implementation extracts error fields that AWS services return at the response level (not nested in the Error dict) and includes them in the error output. For example, DynamoDB returns CancellationReasons at the top level of the response, and this change makes that data accessible.

Examples

DynamoDB TransactionCanceledException

Command:

aws dynamodb transact-write-items \
  --transact-items '[
    {
      "Update": {
        "TableName": "TestErrorTable",
        "Key": {"id": {"S": "existing-item"}},
        "UpdateExpression": "SET #s = :val",
        "ExpressionAttributeNames": {"#s": "status"},
        "ExpressionAttributeValues": {":val": {"S": "updated"}},
        "ConditionExpression": "attribute_not_exists(id)"
      }
    },
    {
      "Put": {
        "TableName": "TestErrorTable",
        "Item": {"id": {"S": "new-item"}}
      }
    }
  ]'

Enhanced format (default):

An error occurred (TransactionCanceledException) when calling the TransactWriteItems operation: Transaction cancelled, please refer cancellation reasons for specific reasons [ConditionalCheckFailed, None]

CancellationReasons: <complex value>
(Use --cli-error-format with json or yaml to see full details)

JSON format (--cli-error-format json):

{
    "Message": "Transaction cancelled, please refer cancellation reasons for specific reasons [ConditionalCheckFailed, None]",
    "Code": "TransactionCanceledException",
    "CancellationReasons": [
        {
            "Code": "ConditionalCheckFailed",
            "Message": "The conditional request failed"
        },
        {
            "Code": "None"
        }
    ]
}

YAML format (--cli-error-format yaml):

CancellationReasons:
- Code: ConditionalCheckFailed
  Message: The conditional request failed
- Code: None
Code: TransactionCanceledException
Message: Transaction cancelled, please refer cancellation reasons for specific reasons
  [ConditionalCheckFailed, None]

Simple error with additional fields

Command:

aws s3api get-object --bucket not-a-real-bucket-0000 --key file.txt out.txt

Enhanced format:

An error occurred (NoSuchBucket) when calling the GetObject operation: The specified bucket does not exist

BucketName: not-a-real-bucket-0000

JSON format:

{
  "Code": "NoSuchBucket",
  "Message": "The specified bucket does not exist",
  "BucketName": "not-a-real-bucket-0000"
}

Enhanced format behavior

The enhanced format handles different error shapes:

Simple values:

  • Strings, numbers, booleans, null
  • Small lists (≤5 simple items): AllowedValues: [GET, PUT, POST, DELETE]
  • Small dicts (≤5 simple key-value pairs): Metadata: {key1: value1, key2: value2}

Complex values:

  • Large collections (>5 items)
  • Nested structures (lists of dicts, nested dicts)
  • Mixed-type collections

When a field is complex, we show:

FieldName: <complex value>
(Use --cli-error-format with json or yaml to see full details)

Configuration

Config file (~/.aws/config):

[default]
cli_error_format = json

Environment variable:

export AWS_CLI_ERROR_FORMAT=yaml

Command-line flag:

aws <command> --cli-error-format enhanced

Valid formats: enhanced (default), json, yaml, text, table, legacy

Use legacy to get the old behavior with no structured error details.

Technical notes

AWS services return modeled error fields at the top level of the error response, not nested under the Error key. For example, DynamoDB returns CancellationReasons at response['CancellationReasons'], not response['Error']['CancellationReasons'].

The implementation:

  1. Copies all fields from response['Error'] (Code, Message, and any service-specific fields there)
  2. Merges in top-level fields from the response (excluding Error, ResponseMetadata, and duplicates)
  3. Returns the combined error dict

Tests

  • All existing tests pass

For reviewers

MAX_INLINE_ITEMS threshold:
Currently set to 5. Could be reduced to 4 for better terminal width compatibility, or we could add a character length limit (~70 chars) in addition to the item count. Open to feedback.

Sensitive data:
AWS service models include @sensitive traits for fields. Right now we display all error fields as returned by the service. Using the Smithy CLI to analyze AWS service models, we found 0 error response fields marked with @sensitive traits.

@AndrewAsseily AndrewAsseily changed the base branch from nyandrew/str-std-error to feature/str-std-error December 3, 2025 20:33
config_var_name='cli_error_format',
session=self.session,
),
ConstantProvider(value='STANDARD'),
Copy link
Member

Choose a reason for hiding this comment

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

Few things on the enum values:

  1. Left a comment elsewhere, but please start by documenting valid values in global_options.rst
  2. Add validation like we do for output for invalid values.
  3. Only STANDARD | LEGACY were never discussed as options, we should revisit with the team internally.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Leaving this comment until we discuss as a team.

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.

2 participants