Skip to content

[Bug] The new proxy credentials have broken Icechunk commits #195

Description

@eeholmes

The new data.source.coop upload proxy supports PUT, GET, HEAD, DELETE,
If-Match, and If-None-Match, but returns 501 for S3 CopyObject:

NotImplemented: server-side copy (x-amz-copy-source) is not supported

Icechunk requires CopyObject during each commit to back up its small mutable
repo-info object before conditionally overwriting it. Writing icechunk stores to Source Coop now fails because of this.

Would it be possible to support same-bucket CopyObject, including
x-amz-copy-source-if-match? Even a GET+PUT fallback for small objects would
restore Icechunk compatibility.

Example code:

import boto3
import json
import uuid
from botocore.exceptions import ClientError

# I save the creds json from UI to this file
with open("source-creds.json") as f:
    creds = json.load(f)

s3 = boto3.client(
    "s3",
    endpoint_url=creds["endpoint_url"],
    region_name=creds["region_name"],
    aws_access_key_id=creds["aws_access_key_id"],
    aws_secret_access_key=creds["aws_secret_access_key"],
    aws_session_token=creds["aws_session_token"],
)

bucket = "fish-pace"
token = uuid.uuid4().hex
source_key = f"globcolour/copyobject-test/source-{token}.txt"
dest_key = f"globcolour/copyobject-test/dest-{token}.txt"

try:
    # Ordinary PUT succeeds
    put_response = s3.put_object(
        Bucket=bucket,
        Key=source_key,
        Body=b"copy test",
    )
    print("PUT:", put_response["ResponseMetadata"]["HTTPStatusCode"])

    source = s3.head_object(Bucket=bucket, Key=source_key)
    etag = source["ETag"]
    print("Source ETag:", etag)

    # Server-side CopyObject fails through data.source.coop
    copy_response = s3.copy_object(
        Bucket=bucket,
        Key=dest_key,
        CopySource={
            "Bucket": bucket,
            "Key": source_key,
        },
        CopySourceIfMatch=etag,
    )

    print(
        "COPY:",
        copy_response["ResponseMetadata"]["HTTPStatusCode"],
    )

except ClientError as e:
    print("HTTP status:", e.response["ResponseMetadata"]["HTTPStatusCode"])
    print("Error code:", e.response["Error"]["Code"])
    print("Message:", e.response["Error"]["Message"])

finally:
    for key in (source_key, dest_key):
        try:
            s3.delete_object(Bucket=bucket, Key=key)
        except Exception:
            pass

Gives this output

PUT: 200
Source ETag: "..."
HTTP status: 501
Error code: NotImplemented
Message: not implemented: server-side copy (x-amz-copy-source) is not supported

Icechunk uses CopyObject to back up its mutable repo object before each commit, so this causes Icechunk commits through https://data.source.coop to fail even though ordinary and conditional PutObject requests succeed.
https://github.com/earth-mover/icechunk/blob/d6e27c56af15edcb95c3cee616520e4a0d1f80ce/icechunk/src/asset_manager.rs#L1583-L1607

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions