Skip to content

Commit

Permalink
ARROW-17079: [C++] Raise proper error message instead of error code f…
Browse files Browse the repository at this point in the history
…or S3 errors (apache#14001)

Part 2 to bring our S3 error messages up to the same standard as the ones from boto3.

The error types are from https://github.com/aws/aws-sdk-cpp/blob/main/aws-cpp-sdk-s3/include/aws/s3/S3Errors.h#L16 -- unfortunately the AWS C++ doesn't seem to have a way to get the errors programmatically from the error codes so we had to hand code them.
The new error format is:

> When getting information for key 'test.csv' in bucket 'pcmoritz-test-bucket-arrow-errors': AWS Error **ACCESS_DENIED** during HeadObject operation: No response body.

The old format was:

> When getting information for key 'test.csv' in bucket 'pcmoritz-test-bucket-arrow-errors': AWS Error **[code 15]** during HeadObject operation: No response body.

Authored-by: Philipp Moritz <[email protected]>
Signed-off-by: Philipp Moritz <[email protected]>
  • Loading branch information
pcmoritz authored and zagto committed Oct 7, 2022
1 parent 2084369 commit 45068a8
Showing 1 changed file with 60 additions and 3 deletions.
63 changes: 60 additions & 3 deletions cpp/src/arrow/filesystem/s3_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,62 @@ inline bool IsAlreadyExists(const Aws::Client::AWSError<Aws::S3::S3Errors>& erro
error_type == Aws::S3::S3Errors::BUCKET_ALREADY_OWNED_BY_YOU);
}

inline std::string S3ErrorToString(Aws::S3::S3Errors error_type) {
switch (error_type) {
#define S3_ERROR_CASE(NAME) \
case Aws::S3::S3Errors::NAME: \
return #NAME;

S3_ERROR_CASE(INCOMPLETE_SIGNATURE)
S3_ERROR_CASE(INTERNAL_FAILURE)
S3_ERROR_CASE(INVALID_ACTION)
S3_ERROR_CASE(INVALID_CLIENT_TOKEN_ID)
S3_ERROR_CASE(INVALID_PARAMETER_COMBINATION)
S3_ERROR_CASE(INVALID_QUERY_PARAMETER)
S3_ERROR_CASE(INVALID_PARAMETER_VALUE)
S3_ERROR_CASE(MISSING_ACTION)
S3_ERROR_CASE(MISSING_AUTHENTICATION_TOKEN)
S3_ERROR_CASE(MISSING_PARAMETER)
S3_ERROR_CASE(OPT_IN_REQUIRED)
S3_ERROR_CASE(REQUEST_EXPIRED)
S3_ERROR_CASE(SERVICE_UNAVAILABLE)
S3_ERROR_CASE(THROTTLING)
S3_ERROR_CASE(VALIDATION)
S3_ERROR_CASE(ACCESS_DENIED)
S3_ERROR_CASE(RESOURCE_NOT_FOUND)
S3_ERROR_CASE(UNRECOGNIZED_CLIENT)
S3_ERROR_CASE(MALFORMED_QUERY_STRING)
S3_ERROR_CASE(SLOW_DOWN)
S3_ERROR_CASE(REQUEST_TIME_TOO_SKEWED)
S3_ERROR_CASE(INVALID_SIGNATURE)
S3_ERROR_CASE(SIGNATURE_DOES_NOT_MATCH)
S3_ERROR_CASE(INVALID_ACCESS_KEY_ID)
S3_ERROR_CASE(REQUEST_TIMEOUT)
S3_ERROR_CASE(NETWORK_CONNECTION)
S3_ERROR_CASE(UNKNOWN)
S3_ERROR_CASE(BUCKET_ALREADY_EXISTS)
S3_ERROR_CASE(BUCKET_ALREADY_OWNED_BY_YOU)
// The following is the most recent addition to S3Errors
// and is not supported yet for some versions of the SDK
// that Apache Arrow is using. This is not a big deal
// since this error will happen only in very specialized
// settings and we will print the correct numerical error
// code as per the "default" case down below. We should
// put it back once the SDK has been upgraded in all
// Apache Arrow build configurations.
// S3_ERROR_CASE(INVALID_OBJECT_STATE)
S3_ERROR_CASE(NO_SUCH_BUCKET)
S3_ERROR_CASE(NO_SUCH_KEY)
S3_ERROR_CASE(NO_SUCH_UPLOAD)
S3_ERROR_CASE(OBJECT_ALREADY_IN_ACTIVE_TIER)
S3_ERROR_CASE(OBJECT_NOT_IN_ACTIVE_TIER)

#undef S3_ERROR_CASE
default:
return "[code " + std::to_string(static_cast<int>(error_type)) + "]";
}
}

// TODO qualify error messages with a prefix indicating context
// (e.g. "When completing multipart upload to bucket 'xxx', key 'xxx': ...")
template <typename ErrorType>
Expand All @@ -96,9 +152,10 @@ Status ErrorToStatus(const std::string& prefix, const std::string& operation,
// XXX Handle fine-grained error types
// See
// https://sdk.amazonaws.com/cpp/api/LATEST/namespace_aws_1_1_s3.html#ae3f82f8132b619b6e91c88a9f1bde371
return Status::IOError(prefix, "AWS Error [code ",
static_cast<int>(error.GetErrorType()), "] during ", operation,
" operation: ", error.GetMessage());
return Status::IOError(
prefix, "AWS Error ",
S3ErrorToString(static_cast<Aws::S3::S3Errors>(error.GetErrorType())), " during ",
operation, " operation: ", error.GetMessage());
}

template <typename ErrorType, typename... Args>
Expand Down

0 comments on commit 45068a8

Please sign in to comment.