Deploy to S3 compatible bucket (Cloudflare R2) - XAmzContentSHA256Mismatch

I am trying to follow the directions from the docs to deply my site to an existing Cloudflare R2 bucket. The site is already there from a manual copy, and I am just testing the sync functionality of hugo deploy.

It correctly identifies a single file when I make a change, so I feel pretty confident that it is reading from the bucket, but it cannot write anything. It gets the following error:

Error: blob (key "index.html") (code=Unknown): XAmzContentSHA256Mismatch: The provided 'x-amz-content-sha256' header does not match what was computed.
        status code: 400, request id: , host id:

I’ve tried digging through the hugo code, and the gocloud.dev/blob code it references, but I can’t quite figure out what the issue is. Is this an error being returned by cloudflare? I don’t know all the nuances of different s3 compatible apis, but is it possible R2 requires a header that isn’t being sent by whatever sdk the blob package is using to write files? Has anyone ever successfully used hugo deploy with Cloudflare R2? Or some other non-S3 endpoint?

Upon further investigation, I have figured out the cause of the issue:

The example blob config for an s3 compatible api included the parameter disableSSL=true and I naively assumed that this was necessary for compatibility reasons. The SDK attempted to PUT my new file in place and got a 301 redirect to try the PUT again at the https protocol. Something inside the sdk then decided to GET the file from that new address instead of retrying the PUT and it was sending the GET request with the same x-amz-content-sha256 as the previous PUT request. This is guaranteed to fail, as this header is computed based on the request, including HTTP verb (GET/PUT) and the canonical URI (including http/https)

Once I removed the disableSSL=true from my s3 compatible URI in my deploy config, it no longer attempted http requests, and the PUT succeeded on the first try.

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.