Skip to content

Commit 3bdf999

Browse files
authored
fix: treat TOS NotFound as missing S3 object (#4165)
1 parent 056f875 commit 3bdf999

1 file changed

Lines changed: 41 additions & 4 deletions

File tree

crates/ragfs/src/plugins/s3fs/client.rs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ where
8383
))
8484
}
8585

86+
fn is_s3_compatible_not_found_code<E>(err: &E) -> bool
87+
where
88+
E: ProvideErrorMetadata,
89+
{
90+
// AWS S3 uses the modeled NoSuchKey error; some TOS direct backends return NotFound.
91+
err.code()
92+
.map(|code| code == "NotFound")
93+
.unwrap_or(false)
94+
}
95+
8696
fn format_sdk_s3_error<E, R>(op: &str, scope: &str, sdk_err: &SdkError<E, R>) -> Error
8797
where
8898
E: std::fmt::Display + ProvideErrorMetadata + RequestId + RequestIdExt,
@@ -512,7 +522,7 @@ impl S3Client {
512522
Ok(resp) => resp,
513523
Err(sdk_err) => {
514524
let service_err = sdk_err.into_service_error();
515-
if service_err.is_no_such_key() {
525+
if service_err.is_no_such_key() || is_s3_compatible_not_found_code(&service_err) {
516526
return Err(Error::NotFound(key.to_string()));
517527
}
518528
return Err(format_s3_service_error(
@@ -545,7 +555,7 @@ impl S3Client {
545555
Ok(resp) => resp,
546556
Err(sdk_err) => {
547557
let service_err = sdk_err.into_service_error();
548-
if service_err.is_no_such_key() {
558+
if service_err.is_no_such_key() || is_s3_compatible_not_found_code(&service_err) {
549559
return Ok(None);
550560
}
551561
return Err(format_s3_service_error(
@@ -592,7 +602,7 @@ impl S3Client {
592602
Ok(resp) => resp,
593603
Err(sdk_err) => {
594604
let service_err = sdk_err.into_service_error();
595-
if service_err.is_no_such_key() {
605+
if service_err.is_no_such_key() || is_s3_compatible_not_found_code(&service_err) {
596606
return Err(Error::NotFound(key.to_string()));
597607
}
598608
return Err(format_s3_service_error(
@@ -846,7 +856,7 @@ impl S3Client {
846856
// Check if it's a 404
847857
if sdk_err
848858
.as_service_error()
849-
.map(|err| err.is_not_found())
859+
.map(|err| err.is_not_found() || is_s3_compatible_not_found_code(err))
850860
.unwrap_or(false)
851861
{
852862
Ok(None)
@@ -1384,4 +1394,31 @@ mod tests {
13841394
other => panic!("expected internal error, got {other:?}"),
13851395
}
13861396
}
1397+
1398+
#[test]
1399+
fn test_is_s3_compatible_not_found_code_accepts_tos_code() {
1400+
let tos_not_found = FakeServiceError {
1401+
raw: "service error",
1402+
meta: ErrorMetadata::builder().code("NotFound").build(),
1403+
};
1404+
assert!(is_s3_compatible_not_found_code(&tos_not_found));
1405+
1406+
let no_such_key = FakeServiceError {
1407+
raw: "service error",
1408+
meta: ErrorMetadata::builder().code("NoSuchKey").build(),
1409+
};
1410+
assert!(!is_s3_compatible_not_found_code(&no_such_key));
1411+
1412+
let access_denied = FakeServiceError {
1413+
raw: "service error",
1414+
meta: ErrorMetadata::builder().code("AccessDenied").build(),
1415+
};
1416+
assert!(!is_s3_compatible_not_found_code(&access_denied));
1417+
1418+
let no_code = FakeServiceError {
1419+
raw: "service error",
1420+
meta: ErrorMetadata::builder().build(),
1421+
};
1422+
assert!(!is_s3_compatible_not_found_code(&no_code));
1423+
}
13871424
}

0 commit comments

Comments
 (0)