-
Notifications
You must be signed in to change notification settings - Fork 266
Description
Describe the bug
CopyObject/UploadPartCopy fails with a NoSuchKey error if the source object contains special characters.
According to AWS documentation, CopyObject/UploadPartCopy's x-amz-copy-source parameter should be URL encoded.
https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html#API_CopyObject_RequestSyntax
https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html#API_UploadPartCopy_RequestSyntax
However the SDK does not URL encode the source object key before sending the request to S3.
For example, if the source object key is etc/alternatives/c++, the SDK fails with a NoSuchKey error.
etc/alternatives/c++ should be encoded as etc/alternatives/c%2B%2B.
Regression Issue
- Select this option if this issue appears to be a regression.
Expected Behavior
aws_sdk_s3::Client::copy_object/upload_part_copy should succeed even if the source object key contains special characters that need to be URL encoded.
Current Behavior
aws_sdk_s3::Client::copy_object/upload_part_copy fails with a NoSuchKey error if the source object contains special characters.
Reproduction Steps
Please run the following code.
use aws_config::BehaviorVersion;
use aws_sdk_s3::primitives::ByteStream;
use tracing_subscriber::filter::EnvFilter;
use tracing_subscriber::fmt::Subscriber;
#[tokio::main]
async fn main() -> Result<(), aws_sdk_s3::Error> {
Subscriber::builder()
.with_env_filter(EnvFilter::new("aws_sigv4=trace"))
.init();
let config = aws_config::defaults(BehaviorVersion::latest()).load().await;
let client = aws_sdk_s3::Client::new(&config);
let content = "Dummy content";
let src_bucket = "XXXXX";
let src_key = "etc/alternatives/c++";
let dst_bucket = "YYYYY";
let dst_key = "etc/alternatives/c++";
client
.put_object()
.bucket(src_bucket)
.key(src_key)
.body(ByteStream::from_static(content.as_bytes()))
.send()
.await?;
let copy_source = format!("{}/{}", src_bucket, src_key);
client
.copy_object()
.bucket(dst_bucket)
.key(dst_key)
.copy_source(copy_source)
.send()
.await?;
Ok(())
}
Possible Solution
URL encoded x-amz-copy-source parameter before sending the request to S3.
Additional Information/Context
No response
Version
$ cargo tree | grep aws-
├── aws-config v1.8.6
│ ├── aws-credential-types v1.2.6
│ │ ├── aws-smithy-async v1.2.5
│ │ ├── aws-smithy-runtime-api v1.9.0
│ │ │ ├── aws-smithy-async v1.2.5 (*)
│ │ │ ├── aws-smithy-types v1.3.2
│ │ ├── aws-smithy-types v1.3.2 (*)
│ ├── aws-runtime v1.5.10
│ │ ├── aws-credential-types v1.2.6 (*)
│ │ ├── aws-sigv4 v1.3.4
│ │ │ ├── aws-credential-types v1.2.6 (*)
│ │ │ ├── aws-smithy-eventstream v0.60.11
│ │ │ │ ├── aws-smithy-types v1.3.2 (*)
│ │ │ ├── aws-smithy-http v0.62.3
│ │ │ │ ├── aws-smithy-eventstream v0.60.11 (*)
│ │ │ │ ├── aws-smithy-runtime-api v1.9.0 (*)
│ │ │ │ ├── aws-smithy-types v1.3.2 (*)
│ │ │ ├── aws-smithy-runtime-api v1.9.0 (*)
│ │ │ ├── aws-smithy-types v1.3.2 (*)
│ │ ├── aws-smithy-async v1.2.5 (*)
│ │ ├── aws-smithy-eventstream v0.60.11 (*)
│ │ ├── aws-smithy-http v0.62.3 (*)
│ │ ├── aws-smithy-runtime v1.9.2
│ │ │ ├── aws-smithy-async v1.2.5 (*)
│ │ │ ├── aws-smithy-http v0.62.3 (*)
│ │ │ ├── aws-smithy-http-client v1.1.1
│ │ │ │ ├── aws-smithy-async v1.2.5 (*)
│ │ │ │ ├── aws-smithy-runtime-api v1.9.0 (*)
│ │ │ │ ├── aws-smithy-types v1.3.2 (*)
│ │ │ │ │ │ ├── aws-lc-rs v1.14.0
│ │ │ │ │ │ │ ├── aws-lc-sys v0.31.0
│ │ │ │ │ │ │ ├── aws-lc-rs v1.14.0 (*)
│ │ │ ├── aws-smithy-observability v0.1.3
│ │ │ │ └── aws-smithy-runtime-api v1.9.0 (*)
│ │ │ ├── aws-smithy-runtime-api v1.9.0 (*)
│ │ │ ├── aws-smithy-types v1.3.2 (*)
│ │ ├── aws-smithy-runtime-api v1.9.0 (*)
│ │ ├── aws-smithy-types v1.3.2 (*)
│ │ ├── aws-types v1.3.8
│ │ │ ├── aws-credential-types v1.2.6 (*)
│ │ │ ├── aws-smithy-async v1.2.5 (*)
│ │ │ ├── aws-smithy-runtime-api v1.9.0 (*)
│ │ │ ├── aws-smithy-types v1.3.2 (*)
│ ├── aws-sdk-sso v1.84.0
│ │ ├── aws-credential-types v1.2.6 (*)
│ │ ├── aws-runtime v1.5.10 (*)
│ │ ├── aws-smithy-async v1.2.5 (*)
│ │ ├── aws-smithy-http v0.62.3 (*)
│ │ ├── aws-smithy-json v0.61.5
│ │ │ └── aws-smithy-types v1.3.2 (*)
│ │ ├── aws-smithy-runtime v1.9.2 (*)
│ │ ├── aws-smithy-runtime-api v1.9.0 (*)
│ │ ├── aws-smithy-types v1.3.2 (*)
│ │ ├── aws-types v1.3.8 (*)
│ ├── aws-sdk-ssooidc v1.85.0
│ │ ├── aws-credential-types v1.2.6 (*)
│ │ ├── aws-runtime v1.5.10 (*)
│ │ ├── aws-smithy-async v1.2.5 (*)
│ │ ├── aws-smithy-http v0.62.3 (*)
│ │ ├── aws-smithy-json v0.61.5 (*)
│ │ ├── aws-smithy-runtime v1.9.2 (*)
│ │ ├── aws-smithy-runtime-api v1.9.0 (*)
│ │ ├── aws-smithy-types v1.3.2 (*)
│ │ ├── aws-types v1.3.8 (*)
│ ├── aws-sdk-sts v1.86.0
│ │ ├── aws-credential-types v1.2.6 (*)
│ │ ├── aws-runtime v1.5.10 (*)
│ │ ├── aws-smithy-async v1.2.5 (*)
│ │ ├── aws-smithy-http v0.62.3 (*)
│ │ ├── aws-smithy-json v0.61.5 (*)
│ │ ├── aws-smithy-query v0.60.7
│ │ │ ├── aws-smithy-types v1.3.2 (*)
│ │ ├── aws-smithy-runtime v1.9.2 (*)
│ │ ├── aws-smithy-runtime-api v1.9.0 (*)
│ │ ├── aws-smithy-types v1.3.2 (*)
│ │ ├── aws-smithy-xml v0.60.10
│ │ ├── aws-types v1.3.8 (*)
│ ├── aws-smithy-async v1.2.5 (*)
│ ├── aws-smithy-http v0.62.3 (*)
│ ├── aws-smithy-json v0.61.5 (*)
│ ├── aws-smithy-runtime v1.9.2 (*)
│ ├── aws-smithy-runtime-api v1.9.0 (*)
│ ├── aws-smithy-types v1.3.2 (*)
│ ├── aws-types v1.3.8 (*)
├── aws-sdk-s3 v1.106.0
│ ├── aws-credential-types v1.2.6 (*)
│ ├── aws-runtime v1.5.10 (*)
│ ├── aws-sigv4 v1.3.4 (*)
│ ├── aws-smithy-async v1.2.5 (*)
│ ├── aws-smithy-checksums v0.63.8
│ │ ├── aws-smithy-http v0.62.3 (*)
│ │ ├── aws-smithy-types v1.3.2 (*)
│ ├── aws-smithy-eventstream v0.60.11 (*)
│ ├── aws-smithy-http v0.62.3 (*)
│ ├── aws-smithy-json v0.61.5 (*)
│ ├── aws-smithy-runtime v1.9.2 (*)
│ ├── aws-smithy-runtime-api v1.9.0 (*)
│ ├── aws-smithy-types v1.3.2 (*)
│ ├── aws-smithy-xml v0.60.10 (*)
│ ├── aws-types v1.3.8 (*)
$
Environment details (OS name and version, etc.)
Linux XXXX 6.8.0-79-generic #79-Ubuntu SMP PREEMPT_DYNAMIC Tue Aug 12 14:42:46 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
Logs
2025-09-16T00:25:57.465803Z TRACE aws_sigv4::http_request::sign: canonical_request=PUT
/etc/alternatives/c%2B%2B
x-id=CopyObject
host:17f10050-97d7-4ba6-bb84-552000698ab7.s3.ap-northeast-1.amazonaws.com
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-copy-source:2ef073f2-f779-4361-956d-052ad0e6e79b/etc/alternatives/c++
x-amz-date:20250916T002557Z
x-amz-user-agent:aws-sdk-rust/1.3.8 ua/2.1 api/s3/1.106.0 os/macos lang/rust/1.89.0 m/E,n md/http#hyper-1.x
host;x-amz-content-sha256;x-amz-copy-source;x-amz-date;x-amz-user-agent
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Error: Unhandled(Unhandled { source: ErrorMetadata { code: Some("NoSuchKey"), message: Some("The specified key does not exist."), extras: Some({"s3_extended_request_id": "nJ0AmnXcJmNbA4F/9WobnaZIgtlH0ac9LWfjFd8s6mnC6e2Ss3Py9ECCDt2U1sf2PAEiZZCQVMU=", "aws_request_id": "AD5WYN1CAMK6RP27"}) }, meta: ErrorMetadata { code: Some("NoSuchKey"), message: Some("The specified key does not exist."), extras: Some({"s3_extended_request_id": "nJ0AmnXcJmNbA4F/9WobnaZIgtlH0ac9LWfjFd8s6mnC6e2Ss3Py9ECCDt2U1sf2PAEiZZCQVMU=", "aws_request_id": "AD5WYN1CAMK6RP27"}) } })