[wrangler] Fix r2 object put and r2 bulk put storing a different key in local mode - #15261
Open
ondraulehla wants to merge 1 commit into
Open
[wrangler] Fix r2 object put and r2 bulk put storing a different key in local mode#15261ondraulehla wants to merge 1 commit into
ondraulehla wants to merge 1 commit into
Conversation
🦋 Changeset detectedLatest commit: dc25a99 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
workers-devprod
requested review from
a team and
penalosa
and removed request for
a team
August 19, 2026 09:01
Contributor
|
Codeowners approval required for this PR:
Show detailed file reviewers
|
ondraulehla
force-pushed
the
fix/r2-local-object-key-encoding
branch
from
August 19, 2026 09:04
588b357 to
dc25a99
Compare
@cloudflare/autoconfig
@cloudflare/build-output-utils
@cloudflare/codemods
@cloudflare/config
create-cloudflare
@cloudflare/deploy-helpers
@cloudflare/kv-asset-handler
miniflare
@cloudflare/pages-functions
@cloudflare/pages-shared
@cloudflare/unenv-preset
@cloudflare/vite-plugin
@cloudflare/vitest-pool-workers
@cloudflare/workers-auth
@cloudflare/workers-editor-shared
@cloudflare/workers-utils
wrangler
commit: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
After #15192 I went looking for the same shape of bug elsewhere in the local-mode commands, and
r2 object puthas one.The key travels to the local bucket worker inside a URL,
dispatchFetch(`http://localhost/${key}`)insrc/r2/object.ts, and the worker pulls it back out withurl.pathname.substring(1). Nothing decodes it, so storage ends up holding whatever URL parsing made of the key.getanddeletenever take that hop. They hand the key straight to the binding, so put writes one name and get looks for another.Six uploads on wrangler 4.124.0, then the keys sitting in
.wrangler/state:Six uploads and five objects. Each one printed "Upload complete.", and the two archives quietly became one. Getting
my report.pdfback afterwards fails with "The specified key does not exist." A%goes one of two ways.50%off.pdfstops on "Invalid URL string.", while%41.txtreports success and lands asA.txt.kv key put "my report.pdf"on the same CLI keeps the space, because the local KV path callsnamespace.put(key, ...)with no URL in the middle.The fix encodes the key going in and decodes it coming out. Keys that work today keep working,
invoices/2026/q1.pdfandmy%20report.pdfboth still round trip. Objects already in local state are left where they are, since nothing gets renamed, so an object an older wrangler stored asmy%20report.pdfis still reachable only under that name. Two keys don't survive either way,.and.., because URL normalisation eats dot segments before any encoding can help. That's the same before and after, and I've left it alone. Bulk put builds the same URL, so it gets the same treatment.Tests in
src/__tests__/r2/local.test.tscover a round trip over seven awkward keys, two keys that differ only after a#, and one bulk put. Without the fix those three fail on "The specified key does not exist." With it,src/__tests__/r2runs 209 of 209.oxfmt --check,oxlint --deny-warnings --type-aware,tsc -p ./tsconfig.jsonandtsc -p ./src/__tests__/tsconfig.jsonare all clean.I've left the remote path alone. It builds the same URL shape in
src/r2/helpers/object.ts, andfetch()drops the fragment before the request goes out. Pointing wrangler at a local server withCLOUDFLARE_API_BASE_URLshows what it sends:Encoding there would send
invoices%2F2026%2Fq1.pdfwhere today it sendsinvoices/2026/q1.pdf, and I have no account to check whether the API reads those the same way. Say which shape you want and I'll add it here.r2 object putandr2 bulk put, no command or option changes