Skip to content

Commit 39779f8

Browse files
authored
Merge pull request #66 from Mytherin/bettererrors
Improve S3 error messages - suggest incorrect region when status code is 400
2 parents 7b09112 + cb26385 commit 39779f8

File tree

2 files changed

+40
-7
lines changed

2 files changed

+40
-7
lines changed

extension/httpfs/include/s3fs.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ class S3FileSystem : public HTTPFileSystem {
223223
return true;
224224
}
225225

226+
static string GetS3BadRequestError(S3AuthParams &s3_auth_params);
227+
static string GetS3AuthError(S3AuthParams &s3_auth_params);
226228
static HTTPException GetS3Error(S3AuthParams &s3_auth_params, const HTTPResponse &response, const string &url);
227229

228230
protected:

extension/httpfs/s3fs.cpp

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,20 @@ void S3FileHandle::Initialize(optional_ptr<FileOpener> opener) {
741741
return;
742742
}
743743
}
744+
auto &extra_info = error.ExtraInfo();
745+
auto entry = extra_info.find("status_code");
746+
if (entry != extra_info.end()) {
747+
if (entry->second == "400") {
748+
// 400: BAD REQUEST
749+
auto extra_text = S3FileSystem::GetS3BadRequestError(auth_params);
750+
throw Exception(error.Type(), error.RawMessage() + extra_text, extra_info);
751+
}
752+
if (entry->second == "403") {
753+
// 403: FORBIDDEN
754+
auto extra_text = S3FileSystem::GetS3AuthError(auth_params);
755+
throw Exception(error.Type(), error.RawMessage() + extra_text, extra_info);
756+
}
757+
}
744758
throw;
745759
}
746760

@@ -973,26 +987,43 @@ bool S3FileSystem::ListFiles(const string &directory, const std::function<void(c
973987
return true;
974988
}
975989

976-
HTTPException S3FileSystem::GetS3Error(S3AuthParams &s3_auth_params, const HTTPResponse &response, const string &url) {
977-
string region = s3_auth_params.region;
990+
string S3FileSystem::GetS3BadRequestError(S3AuthParams &s3_auth_params) {
991+
string extra_text = "\n\nBad Request - this can be caused by the S3 region being set incorrectly.";
992+
if (s3_auth_params.region.empty()) {
993+
extra_text += "\n* No region is provided.";
994+
} else {
995+
extra_text += "\n* Provided region is \"" + s3_auth_params.region + "\"";
996+
}
997+
return extra_text;
998+
}
999+
1000+
string S3FileSystem::GetS3AuthError(S3AuthParams &s3_auth_params) {
9781001
string extra_text = "\n\nAuthentication Failure - this is usually caused by invalid or missing credentials.";
9791002
if (s3_auth_params.secret_access_key.empty() && s3_auth_params.access_key_id.empty()) {
9801003
extra_text += "\n* No credentials are provided.";
9811004
} else {
9821005
extra_text += "\n* Credentials are provided, but they did not work.";
9831006
}
9841007
extra_text += "\n* See https://duckdb.org/docs/stable/extensions/httpfs/s3api.html";
1008+
return extra_text;
1009+
}
1010+
1011+
HTTPException S3FileSystem::GetS3Error(S3AuthParams &s3_auth_params, const HTTPResponse &response, const string &url) {
1012+
string extra_text;
1013+
if (response.status == HTTPStatusCode::BadRequest_400) {
1014+
extra_text = GetS3BadRequestError(s3_auth_params);
1015+
}
1016+
if (response.status == HTTPStatusCode::Forbidden_403) {
1017+
extra_text = GetS3AuthError(s3_auth_params);
1018+
}
9851019
auto status_message = HTTPFSUtil::GetStatusMessage(response.status);
9861020
throw HTTPException(response, "HTTP GET error reading '%s' in region '%s' (HTTP %d %s)%s", url,
9871021
s3_auth_params.region, response.status, status_message, extra_text);
9881022
}
9891023

9901024
HTTPException S3FileSystem::GetHTTPError(FileHandle &handle, const HTTPResponse &response, const string &url) {
991-
if (response.status == HTTPStatusCode::Forbidden_403) {
992-
auto &s3_handle = handle.Cast<S3FileHandle>();
993-
return GetS3Error(s3_handle.auth_params, response, url);
994-
}
995-
return HTTPFileSystem::GetHTTPError(handle, response, url);
1025+
auto &s3_handle = handle.Cast<S3FileHandle>();
1026+
return GetS3Error(s3_handle.auth_params, response, url);
9961027
}
9971028
string AWSListObjectV2::Request(string &path, HTTPParams &http_params, S3AuthParams &s3_auth_params,
9981029
string &continuation_token, optional_ptr<HTTPState> state, bool use_delimiter) {

0 commit comments

Comments
 (0)