@@ -741,6 +741,20 @@ void S3FileHandle::Initialize(optional_ptr<FileOpener> opener) {
741
741
return ;
742
742
}
743
743
}
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
+ }
744
758
throw ;
745
759
}
746
760
@@ -973,26 +987,43 @@ bool S3FileSystem::ListFiles(const string &directory, const std::function<void(c
973
987
return true ;
974
988
}
975
989
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\n Bad 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) {
978
1001
string extra_text = " \n\n Authentication Failure - this is usually caused by invalid or missing credentials." ;
979
1002
if (s3_auth_params.secret_access_key .empty () && s3_auth_params.access_key_id .empty ()) {
980
1003
extra_text += " \n * No credentials are provided." ;
981
1004
} else {
982
1005
extra_text += " \n * Credentials are provided, but they did not work." ;
983
1006
}
984
1007
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
+ }
985
1019
auto status_message = HTTPFSUtil::GetStatusMessage (response.status );
986
1020
throw HTTPException (response, " HTTP GET error reading '%s' in region '%s' (HTTP %d %s)%s" , url,
987
1021
s3_auth_params.region , response.status , status_message, extra_text);
988
1022
}
989
1023
990
1024
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);
996
1027
}
997
1028
string AWSListObjectV2::Request (string &path, HTTPParams &http_params, S3AuthParams &s3_auth_params,
998
1029
string &continuation_token, optional_ptr<HTTPState> state, bool use_delimiter) {
0 commit comments