Skip to content

Commit 45068a8

Browse files
pcmoritzzagto
authored andcommitted
ARROW-17079: [C++] Raise proper error message instead of error code for 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 <pcmoritz@gmail.com> Signed-off-by: Philipp Moritz <pcmoritz@gmail.com>
1 parent 2084369 commit 45068a8

File tree

1 file changed

+60
-3
lines changed

1 file changed

+60
-3
lines changed

cpp/src/arrow/filesystem/s3_internal.h

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,62 @@ inline bool IsAlreadyExists(const Aws::Client::AWSError<Aws::S3::S3Errors>& erro
8888
error_type == Aws::S3::S3Errors::BUCKET_ALREADY_OWNED_BY_YOU);
8989
}
9090

91+
inline std::string S3ErrorToString(Aws::S3::S3Errors error_type) {
92+
switch (error_type) {
93+
#define S3_ERROR_CASE(NAME) \
94+
case Aws::S3::S3Errors::NAME: \
95+
return #NAME;
96+
97+
S3_ERROR_CASE(INCOMPLETE_SIGNATURE)
98+
S3_ERROR_CASE(INTERNAL_FAILURE)
99+
S3_ERROR_CASE(INVALID_ACTION)
100+
S3_ERROR_CASE(INVALID_CLIENT_TOKEN_ID)
101+
S3_ERROR_CASE(INVALID_PARAMETER_COMBINATION)
102+
S3_ERROR_CASE(INVALID_QUERY_PARAMETER)
103+
S3_ERROR_CASE(INVALID_PARAMETER_VALUE)
104+
S3_ERROR_CASE(MISSING_ACTION)
105+
S3_ERROR_CASE(MISSING_AUTHENTICATION_TOKEN)
106+
S3_ERROR_CASE(MISSING_PARAMETER)
107+
S3_ERROR_CASE(OPT_IN_REQUIRED)
108+
S3_ERROR_CASE(REQUEST_EXPIRED)
109+
S3_ERROR_CASE(SERVICE_UNAVAILABLE)
110+
S3_ERROR_CASE(THROTTLING)
111+
S3_ERROR_CASE(VALIDATION)
112+
S3_ERROR_CASE(ACCESS_DENIED)
113+
S3_ERROR_CASE(RESOURCE_NOT_FOUND)
114+
S3_ERROR_CASE(UNRECOGNIZED_CLIENT)
115+
S3_ERROR_CASE(MALFORMED_QUERY_STRING)
116+
S3_ERROR_CASE(SLOW_DOWN)
117+
S3_ERROR_CASE(REQUEST_TIME_TOO_SKEWED)
118+
S3_ERROR_CASE(INVALID_SIGNATURE)
119+
S3_ERROR_CASE(SIGNATURE_DOES_NOT_MATCH)
120+
S3_ERROR_CASE(INVALID_ACCESS_KEY_ID)
121+
S3_ERROR_CASE(REQUEST_TIMEOUT)
122+
S3_ERROR_CASE(NETWORK_CONNECTION)
123+
S3_ERROR_CASE(UNKNOWN)
124+
S3_ERROR_CASE(BUCKET_ALREADY_EXISTS)
125+
S3_ERROR_CASE(BUCKET_ALREADY_OWNED_BY_YOU)
126+
// The following is the most recent addition to S3Errors
127+
// and is not supported yet for some versions of the SDK
128+
// that Apache Arrow is using. This is not a big deal
129+
// since this error will happen only in very specialized
130+
// settings and we will print the correct numerical error
131+
// code as per the "default" case down below. We should
132+
// put it back once the SDK has been upgraded in all
133+
// Apache Arrow build configurations.
134+
// S3_ERROR_CASE(INVALID_OBJECT_STATE)
135+
S3_ERROR_CASE(NO_SUCH_BUCKET)
136+
S3_ERROR_CASE(NO_SUCH_KEY)
137+
S3_ERROR_CASE(NO_SUCH_UPLOAD)
138+
S3_ERROR_CASE(OBJECT_ALREADY_IN_ACTIVE_TIER)
139+
S3_ERROR_CASE(OBJECT_NOT_IN_ACTIVE_TIER)
140+
141+
#undef S3_ERROR_CASE
142+
default:
143+
return "[code " + std::to_string(static_cast<int>(error_type)) + "]";
144+
}
145+
}
146+
91147
// TODO qualify error messages with a prefix indicating context
92148
// (e.g. "When completing multipart upload to bucket 'xxx', key 'xxx': ...")
93149
template <typename ErrorType>
@@ -96,9 +152,10 @@ Status ErrorToStatus(const std::string& prefix, const std::string& operation,
96152
// XXX Handle fine-grained error types
97153
// See
98154
// https://sdk.amazonaws.com/cpp/api/LATEST/namespace_aws_1_1_s3.html#ae3f82f8132b619b6e91c88a9f1bde371
99-
return Status::IOError(prefix, "AWS Error [code ",
100-
static_cast<int>(error.GetErrorType()), "] during ", operation,
101-
" operation: ", error.GetMessage());
155+
return Status::IOError(
156+
prefix, "AWS Error ",
157+
S3ErrorToString(static_cast<Aws::S3::S3Errors>(error.GetErrorType())), " during ",
158+
operation, " operation: ", error.GetMessage());
102159
}
103160

104161
template <typename ErrorType, typename... Args>

0 commit comments

Comments
 (0)