Summary
In a legacy etcd bucket-federation deployment, a whole-object CopyObject that crosses deployments returns 200 with no checksum, even when the client explicitly requests one. The request is neither honored nor rejected.
This is the whole-object counterpart of #72, which fixed the same class of problem for federated UploadPartCopy.
Evidence
Driven through the real federation branch (a second HTTP endpoint serving the remote deployment, forwarding through getRemoteInstanceClient and minio-go), on both object-layer backends:
PUT /remoteBucket/dst
x-amz-copy-source: /srcBucket/src
x-amz-checksum-algorithm: CRC32
->
200
<CopyObjectResult><LastModified>…</LastModified><ETag>"…"</ETag></CopyObjectResult>
response ChecksumCRC32 = "" want "3aNLCg=="
response ChecksumType = ""
The local (non-federated) path returns the checksum correctly, so the two paths now disagree.
Cause
cmd/object-handlers.go, federated branch of CopyObjectHandler:
remoteObjInfo, rerr := core.PutObject(ctx, dstBucket, dstObject, srcInfo.Reader,
srcInfo.Size, "", "", opts)
...
objInfo.UserDefined = cloneMSS(opts.UserMetadata)
objInfo.ETag = remoteObjInfo.ETag
objInfo.ModTime = remoteObjInfo.LastModified
Two gaps:
remoteObjInfo.ChecksumCRC32/CRC32C/SHA1/SHA256/CRC64NVME are discarded, so the later objInfo.decryptChecksums(...) finds nothing to return.
- The
miniogo.PutObjectOptions passed to the remote write carries no checksum algorithm, so the remote deployment is never asked to compute one either — the object is persisted without a checksum too.
Provenance and scope
The federated branch is byte-identical to RELEASE.2026-08-06T00-00-00Z, so this is not a regression. It became visible because f2520f334 added checksums to the CopyObject response for the local path, and the federated path was not covered.
Affects only legacy etcd bucket federation (globalDNSConfig set and MINIO_BUCKET_FEDERATION enabled), which upstream has deprecated. Not release-gating.
Expected
Either return and persist the requested checksum on the federated path, matching the local path and #72, or reject a checksum request that the federated path cannot satisfy. Silently discarding it is the one behavior that should not remain.
Summary
In a legacy etcd bucket-federation deployment, a whole-object
CopyObjectthat crosses deployments returns 200 with no checksum, even when the client explicitly requests one. The request is neither honored nor rejected.This is the whole-object counterpart of #72, which fixed the same class of problem for federated
UploadPartCopy.Evidence
Driven through the real federation branch (a second HTTP endpoint serving the remote deployment, forwarding through
getRemoteInstanceClientand minio-go), on both object-layer backends:The local (non-federated) path returns the checksum correctly, so the two paths now disagree.
Cause
cmd/object-handlers.go, federated branch ofCopyObjectHandler:Two gaps:
remoteObjInfo.ChecksumCRC32/CRC32C/SHA1/SHA256/CRC64NVMEare discarded, so the laterobjInfo.decryptChecksums(...)finds nothing to return.miniogo.PutObjectOptionspassed to the remote write carries no checksum algorithm, so the remote deployment is never asked to compute one either — the object is persisted without a checksum too.Provenance and scope
The federated branch is byte-identical to
RELEASE.2026-08-06T00-00-00Z, so this is not a regression. It became visible becausef2520f334added checksums to theCopyObjectresponse for the local path, and the federated path was not covered.Affects only legacy etcd bucket federation (
globalDNSConfigset andMINIO_BUCKET_FEDERATIONenabled), which upstream has deprecated. Not release-gating.Expected
Either return and persist the requested checksum on the federated path, matching the local path and #72, or reject a checksum request that the federated path cannot satisfy. Silently discarding it is the one behavior that should not remain.