All skills
aws avatar

/aws-sdk-python-usage

@c3ed514

AWS SDK for Python (boto3/botocore) development patterns. You MUST use this skill when writing Python code that uses AWS services via boto3 or botocore. This includes creating service clients or resources, configuring sessions and credentials, handling errors with ClientError, using paginators and waiters, S3 file transfers and presigned URLs, DynamoDB table operations, and any boto3/botocore client configuration. Use this skill whenever Python code imports boto3 or botocore, or when the user asks about AWS operations in Python.

Use this Skill: https://skilld.dev/gh/aws/agent-toolkit-for-aws/aws-sdk-python-usage

This session only. Nothing lands on disk.

referenceserror-handling.md

≈1.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Error Handling Reference

Core Principle

Only catch an exception when you have an actionable response: return a fallback, retry, take a different code path. If the only thing you'd do is print the error, don't catch it -- let it propagate. The caller (or a top-level handler) is in a better position to decide what to do.

ClientError Anatomy

botocore.exceptions.ClientError is the base exception for all AWS API errors:

from botocore.exceptions import ClientError

try:
    client.describe_instances(InstanceIds=["i-nonexistent"])
except ClientError as e:
    error = e.response["Error"]
    metadata = e.response["ResponseMetadata"]

    error["Code"]               # "InvalidInstanceID.NotFound"
    error["Message"]            # "The instance ID 'i-nonexistent' does not exist"
    metadata["HTTPStatusCode"]  # 400
    metadata["RequestId"]       # AWS request ID for support cases

Service-Specific Exceptions

Each client exposes typed exceptions generated from the service model. These are subclasses of ClientError, so a ClientError catch still works as a fallback:

s3 = boto3.client("s3")
try:
    s3.get_object(Bucket="bucket", Key="key")
except s3.exceptions.NoSuchKey:
    return None  # actionable: missing key is a valid case

List available exceptions for a client:

print([e for e in dir(s3.exceptions) if not e.startswith("_")])

Common botocore Exceptions

from botocore.exceptions import (
    ClientError,              # AWS API returned an error response
    NoCredentialsError,       # no credentials found in the chain
    PartialCredentialsError,  # incomplete credentials (e.g. key without secret)
    NoRegionError,            # no region configured
    ParamValidationError,     # invalid parameters before request is sent
    EndpointConnectionError,  # could not connect to the endpoint
    ConnectTimeoutError,      # connection timed out
    ReadTimeoutError,         # read timed out waiting for response
    WaiterError,              # waiter reached max attempts without success
)

ParamValidationError is raised locally before any network request -- it means the parameters failed botocore's client-side validation.

Error Handling Patterns

Actionable catch: convert to return value

def get_item(table, key: dict) -> dict | None:
    response = table.get_item(Key=key)
    return response.get("Item")  # None if missing, no exception needed

def head_object(client, bucket: str, key: str) -> dict | None:
    try:
        return client.head_object(Bucket=bucket, Key=key)
    except client.exceptions.ClientError as e:
        if e.response["ResponseMetadata"]["HTTPStatusCode"] == 404:
            return None
        raise

Actionable catch: conditional put race

try:
    table.put_item(
        Item=new_item,
        ConditionExpression=Attr("pk").not_exists(),
    )
except table.meta.client.exceptions.ConditionalCheckFailedException:
    # Another writer got there first -- fetch what they wrote
    return table.get_item(Key={"pk": new_item["pk"]})["Item"]

Actionable catch: create-if-not-exists

try:
    client.create_bucket(Bucket="my-bucket")
except client.exceptions.BucketAlreadyOwnedByYou:
    pass  # already exists, that's fine

Top-level catch-all in main()

Business logic functions should let exceptions propagate. The main() function is the right place for a generic catch-all that presents errors cleanly to the user. Keep the catch-all simple -- just ClientError. Other exceptions like NoCredentialsError already have clear messages and can propagate naturally:

from botocore.exceptions import ClientError

def main() -> int:
    try:
        do_the_work()
        return 0
    except ClientError as e:
        print(f"Error: {e}", file=sys.stderr)
        return 1

if __name__ == "__main__":
    sys.exit(main())

What NOT to do

# Wrong: catching just to print and swallow
try:
    client.describe_table(TableName=name)
except client.exceptions.ResourceNotFoundException:
    print("Table not found")     # swallowed -- caller has no idea it failed
except NoCredentialsError:
    print("No credentials")      # swallowed
except EndpointConnectionError:
    print("Can't connect")       # swallowed

# Wrong: sys.exit() from a business logic function
def process_queue(queue_url):
    if not queue_url:
        print("No queue URL provided")
        sys.exit(1)              # untestable, unusable as library code

Source: SKILL.md on GitHub

No alerts16d3 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill provides comprehensive guidance and best practices for using the AWS SDK for Python (boto3/botocore). It covers essential topics such as session management, credential resolution, error handling, and service-specific patterns for S3 and DynamoDB. The skill aligns with security best practices, particularly regarding credential management and robust application configuration.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

Signed by skilld at c3ed514. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 5 months ago

README badge

README badge for aws/agent-toolkit-for-aws/aws-sdk-python-usage