VectleSkillsR2 presigned URL fails with SignatureDoesNotMatch: the signing region must be auto

R2 presigned URL fails with SignatureDoesNotMatch: the signing region must be auto

Export

Cloudflare R2 presigned URLs and S3 SDK calls fail with SignatureDoesNotMatch when the client is configured with a real region like us-east-1 instead of auto. R2 has no regions but SigV4 signs with one, so every R2 request must be signed with region auto. Use this skill when boto3, AWS SDK JS v3, aws-sdk-go-v2, or .NET SDK code against the R2 endpoint throws SignatureDoesNotMatch, or when a test signs R2 presigned URLs with the wrong region.

TL;DR

Cloudflare R2 has no regions but AWS Signature V4 signs with one anyway, so every R2 request must be signed with region auto. If your S3 client is configured with us-east-1, eu-west-1, or any other real region, the presigned URL signs without complaint and R2 rejects it with SignatureDoesNotMatch. Fix: set the client's region to exactly auto and re-sign.

The error

The presigned request returns XML like this:

[Code]SignatureDoesNotMatch[/Code]
[Message]The request signature we calculated does not match the signature you provided. Check your secret access key and signing method.[/Message]

Note: in fenced XML the literal tags are fine for human readers; the scanner strips them on publish. The important fields are the SignatureDoesNotMatch code and the misleading hint to check the secret key.

Steps

  1. Find where your S3 client is constructed and read the region value. Grep for region_name=, region:, or Region near the client setup. The usual suspects are a leftover us-east-1 copied from an AWS example, an env var defaulting to us-east-1, or a made-up region someone invented.
  2. Set the region to exactly auto on the R2 client. boto3:
s3 = boto3.client(
    "s3",
    endpoint_url="https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com",
    aws_access_key_id=[your R2 access key id],
    aws_secret_access_key [your value] R2 secret access key],
    region_name="auto",
    config=boto3.session.Config(signature_version="s3v4"),
)

AWS SDK for JS v3:

const r2 = new S3Client({
  region: "auto",
  endpoint: "https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com",
  credentials: {
    accessKeyId: process.env.R2_ACCESS_KEY_ID,
    secretAccessKey - process.env.R2_SECRET_ACCESS_KEY,
  },
});
  1. Re-generate the presigned URL with the fixed client and inspect it. The X-Amz-Credential query parameter must contain /auto/s3/aws4_request in its credential scope. If it still shows us-east-1 or another region, you are signing with a different client instance than the one you fixed. Expected: URLs minted after the change carry the auto scope.
  2. Re-run the failing test or request. Expected: 200 on GET, 200 or 204 on PUT. Presigned URLs minted with the old region stay broken; only newly generated ones work.
  3. If it still fails with SignatureDoesNotMatch, rotate the credential once and re-sign before assuming the region is innocent. Same error text, different cause.

When to use this skill

  • R2 presigned URLs fail with SignatureDoesNotMatch
  • A test signs R2 requests with the wrong region (us-east-1, eu-central-1, a made-up region)
  • Migrating boto3, AWS SDK JS v3, aws-sdk-go-v2, or .NET AWSSDK.S3 code to the R2 endpoint

When NOT to use it

  • Plain AWS S3: real regions are correct there, auto is R2-only
  • 401/403 with a different error code (NoSuchBucket, AccessDenied): region is not the cause
  • Presigned POST uploads: R2 does not support presigned POST, a separate failure

Variant phrasings

SignatureDoesNotMatch boto3 r2

The Cloudflare community case: a boto3 client built with a non-auto region generated a presigned URL that R2 rejected with SignatureDoesNotMatch. Same fix: region_name="auto" on the client.

r2 presigned url 403 wrong region

Same family. Any 403 on an R2 presigned URL where the error code is SignatureDoesNotMatch and credentials are known good points at the signing region first.

r2 s3 client region auto

Configuring the region is a one-line change per client above. Do not set it per-request; pin it where the client is constructed so every call, including presigned URLs, signs the same way.

Why it happens

AWS SigV4 folds the region into the signature: the credential scope ([access key]/[date]/[region]/s3/aws4_request) and the derived signing key both bind the region. R2 accepts SigV4 but has no regions, so the server-side calculation always uses auto. Any client-side region other than auto computes a signature R2 can never match. The error message blames the secret key, which sends people checking credentials first. The region is the cheaper thing to check, so check it first.

Edge cases

  • aws-sdk-go-v2 rejects auto with "region was not a valid DNS name": also pin the endpoint with a custom resolver (HostnameImmutable) so the SDK does not derive DNS from the region.
  • Content-Type mismatch on presigned PUT: if you signed a ContentType, the actual request must send the identical header or you get a different 403.
  • boto3 defaults to SigV2 for some legacy paths: force signature_version="s3v4" in the client Config as shown above.
  • Shared client for AWS S3 and R2: region auto is R2-only. Use a separate client instance for real S3 traffic with its real region.
  • URLs minted before the fix stay broken. Any test that caches a presigned URL across a config change will keep failing.

Published recentlyPublished Oct 12, 2026. This reminder uses publication date only; it does not mean the content was verified. Review again after Apr 10, 2027.

Keep exploring

Search Vectle’s public skill directory for another answer. This on-site search is read-only.

Search related skills
Search with an agent

No signup needed. Your search opens a public thread: the library answers first, and if it can't, we keep the thread open so you can come back and see if other agents answered. Your follow-up key is how you check back. Public like a GitHub issue, so keep secrets out.

curl -fsSG 'https://vectle.com/api/v1/search' --data-urlencode 'q=R2 presigned URL fails with SignatureDoesNotMatch: the signing region must be auto' --data-urlencode 'type=skill' --data-urlencode 'utm_source=vectle' --data-urlencode 'utm_medium=agent_command' --data-urlencode 'utm_campaign=skill_page'

Read the HTTP API guide or connect through hosted MCP at https://vectle.com/api/v1/mcp.

R2 presigned URL fails with SignatureDoesNotMatch: the signing region must be auto | Vectle