Handling errors in the AWS SDK for Rust (original) (raw)
Understanding how and when the AWS SDK for Rust returns errors is important to building high-quality applications using the SDK. The following sections describe the different errors you might encounter from the SDK and how to handle them appropriately.
Every operation returns a Result
type with the error type set to SdkError<E, R = HttpResponse>. SdkError
is an enum with several possible types, called variants.
Service errors
The most common type of error is SdkError::ServiceError. This error represents an error response from an AWS service. For example, if you try to get an object from Amazon S3 that doesn't exist, Amazon S3 returns an error response.
When you encounter an SdkError::ServiceError
it means that your request was successfully sent to the AWS service but could not be processed. This can be because of errors in the request's parameters or because of issues on the service side.
The error response details are included in the error variant. The following example shows how to conveniently get at the underlying ServiceError
variant and handle different error cases:
// Needed to access the '.code()' function on the error type:
use aws_sdk_s3::error::ProvideErrorMetadata;
let result = s3.get_object()
.bucket("my-bucket")
.key("my-key")
.send()
.await;
match result {
Ok(_output) => { /* Success. Do something with the output. */ }
Err(err) => match err.into_service_error() {
GetObjectError::InvalidObjectState(value) => {
println!("invalid object state: {:?}", value);
}
GetObjectError::NoSuchKey(_) => {
println!("object didn't exist");
}
// err.code() returns the raw error code from the service and can be
// used as a last resort for handling unmodeled service errors.
err if err.code() == Some("SomeUnmodeledError") => {}
err => return Err(err.into())
}
};
Every service error has additional metadata that can be accessed by importing service-specific traits.
- The
`<service>`::error::ProvideErrorMetadata
trait provides access to any available underlying raw error code and error message returned from the service.- For Amazon S3, this trait is aws_sdk_s3::error::ProvideErrorMetadata.
You can also get information that might be useful when troubleshooting service errors:
- The
`<service>`::operation::RequestId
trait adds extension methods to retrieve the unique AWS request ID that was generated by the service.- For Amazon S3, this trait is aws_sdk_s3::operation::RequestId.
- The
`<service>`::operation::RequestIdExt
trait adds theextended_request_id()
method to get an additional, extended request ID.- Only supported by some services.
- For Amazon S3, this trait is aws_sdk_s3::operation::RequestIdExt.
Detailed error printing withDisplayErrorContext
Errors in the SDK are generally the result of a chain of failures such as:
- Dispatching a request has failed because the connector returned an error.
- The connector returned an error because the credentials provider returned an error.
- The credentials provider returned an error because it called a service and that service returned an error.
- The service returned an error because the credentials request didn't have the correct authorization.
By default, display of this error only outputs "dispatch failure". This lacks details that help troubleshoot the error. The SDK for Rust provides a simple error reporter calledDisplayErrorContext
.
- The
`<service>`::error::DisplayErrorContext
struct adds functionality to output the full error context.- For Amazon S3, this struct is aws_sdk_s3::error::DisplayErrorContext.
When we wrap the error to be displayed and print it, DisplayErrorContext
provides a much more detailed message similar to the following:
dispatch failure: other: Session token not found or invalid.
DispatchFailure(
DispatchFailure {
source: ConnectorError {
kind: Other(None),
source: ProviderError(
ProviderError {
source: ProviderError(
ProviderError {
source: ServiceError(
ServiceError {
source: UnauthorizedException(
UnauthorizedException {
message: Some("Session token not found or invalid"),
meta: ErrorMetadata {
code: Some("UnauthorizedException"),
message: Some("Session token not found or invalid"),
extras: Some({"aws_request_id": "1b6d7476-f5ec-4a16-9890-7684ccee7d01"})
}
}
),
raw: Response {
status: StatusCode(401),
headers: Headers {
headers: {
"date": HeaderValue { _private: H0("Thu, 04 Jul 2024 07:41:21 GMT") },
"content-type": HeaderValue { _private: H0("application/json") },
"content-length": HeaderValue { _private: H0("114") },
"access-control-expose-headers": HeaderValue { _private: H0("RequestId") },
"access-control-expose-headers": HeaderValue { _private: H0("x-amzn-RequestId") },
"requestid": HeaderValue { _private: H0("1b6d7476-f5ec-4a16-9890-7684ccee7d01") },
"server": HeaderValue { _private: H0("AWS SSO") },
"x-amzn-requestid": HeaderValue { _private: H0("1b6d7476-f5ec-4a16-9890-7684ccee7d01") }
}
},
body: SdkBody {
inner: Once(
Some(
b"{
\"message\":\"Session token not found or invalid\",
\"__type\":\"com.amazonaws.switchboard.portal#UnauthorizedException\"}"
)
),
retryable: true
},
extensions: Extensions {
extensions_02x: Extensions,
extensions_1x: Extensions
}
}
}
)
}
)
}
),
connection: Unknown
}
}
)