Guide

Connect big binaries over a slow network

Connect multi-MB payloads into the core, why we bind `content_length` into the URL, and how to read a "size mismatch" 403 from R2.

5/18/2026 · connect0 · 4 min

Connect large binaries into the core reliably, even over flaky links — and know exactly what a size-mismatch 403 is telling you.

A 200 MB tarball, a 50 MB SQLite snapshot, a multi-hour audio file — these are exactly the payloads upload.create_link is for. They're also where surprising 403s lurk if you don't know how the URL is bound.

content_length is signed into the URL

Cloudflare R2 doesn't honour S3's content-length-range policy. The closest thing we have is signing a specific Content-Length value into the pre-signed URL. So when the agent passes content_length: 209715200 (200 MiB), it's making a one-shot promise: "the user will PUT exactly 209,715,200 bytes."

If the file is 209,715,201 bytes, R2 returns:

HTTP 403  SignatureDoesNotMatch

That's not a permission error — the signature is over (method, key, headers including Content-Length), and a different size flips the signature.

Two postures

You know the exact size. Pass it. The URL is strictly bound. Useful for finalising a deterministic artifact ("the agent computed this checksum, the file should be exactly N bytes").

You don't. Omit content_length. The URL accepts any size up to R2's 4.995 TiB single-PUT cap. The audit ledger still records the bytes R2 reports — there's no defence-in-depth size cap, just the observability.

What "exact" means

Bytes, not characters. Not lines. Not "size on disk." Run it through wc -c:

wc -c < ./big.tar.gz

The number wc prints is what to pass.

Network-adjacent failure modes

  • Truncated upload. Network drops mid-PUT. R2 sees less than the signed size, returns 403. Retry — pre-signed URLs are good until they expire.
  • Modem reset adds bytes. Less common in 2026 but still happens with proxy retries. Same 403. Try with --connect-timeout and a single TCP connection.
  • gzip middleware on a proxy. If something between you and R2 is decompressing/recompressing the body, the size changes. 403. Workaround: pass -H 'content-encoding: identity' to curl to discourage middleware.

Use the browser helper for big files

The browser-helper page at /u/[token] PUTs with XMLHttpRequest and reports byte-level progress. For multi-GB files over flaky links it's friendlier than curl — you can see where you are, and a tab crash doesn't silently corrupt the upload.

Multipart (future)

R2's S3 API supports multipart for files where a single PUT is awkward. We don't expose multipart from upload.create_link today. When we do, the tool will grow a mode: "multipart" flag and the response shape will return part URLs instead of one URL. Single-PUT is fine up to ~100 MiB on most networks.

Next steps

Where this fits

This is the Connect everything pillar of connect0 — the core that connects everything your company runs on. Big, awkward binaries are exactly the payloads pre-signed links exist for, so even multi-GB sources connect cleanly into the core. Start building → · All guides →