[miniflare] Fix KV bulk getWithMetadata dropping metadata for falsy values#14762
[miniflare] Fix KV bulk getWithMetadata dropping metadata for falsy values#14762gianghungtien wants to merge 2 commits into
getWithMetadata dropping metadata for falsy values#14762Conversation
…alues
The bulk-get handler in `processKeyValue` decided whether to wrap an entry
as `{ value, metadata }` based on the truthiness of the decoded value rather
than on whether the key existed. Present keys holding a falsy value - an
empty string, or `0`, `false` and `null` when read with `type: "json"` -
were returned as bare values, losing their metadata and diverging from the
shape the runtime binding expects for present keys.
Gate the wrapper on entry presence instead. `storage.get()` returns `null`
only for missing keys, and a present entry always carries a `value`
ReadableStream, so `obj !== null` is the correct presence check. Missing
keys continue to return a bare `null`.
Also switch the two preceding `obj?.value` truthiness checks to the same
explicit presence check. These are equivalent - a present entry's `value`
is always a non-null stream - but make the invariant clear at each site.
🦋 Changeset detectedLatest commit: b34f696 The changes in this PR will be included in the next version bump. This PR includes changesets to release 7 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 |
|
Codeowners approval required for this PR:
Show detailed file reviewers
|
Addresses review feedback. The annotations were copied from the surrounding bulk get tests; dropping them and letting inference do the work type-checks cleanly and reads better. Annotating the expected Maps with the real result type isn't an option here: `KVNamespaceGetWithMetadataResult` declares a `cacheStatus` field that the bulk endpoint doesn't return, so the literals would have to carry a property the assertion would then fail on.
@cloudflare/autoconfig
@cloudflare/config
create-cloudflare
@cloudflare/deploy-helpers
@cloudflare/kv-asset-handler
miniflare
@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: |
|
@NuroDev this should be ready for another look when you have a moment — the Separately, this is also blocked on I believe it's unrelated to this PR:
For completeness: other currently-open PRs are passing this job, so this doesn't look like broad breakage — just an intermittent Windows failure that has caught both of mine. If a re-run reproduces it I'll investigate properly rather than keep calling it flaky. The miniflare KV suite itself is green (54/54), and I re-confirmed the three new tests still fail without the fix after removing the |
Fixes #14594.
The KV bulk-get handler (
@POST("/bulk/get")) decides whether to wrap each entry as{ value, metadata }based on the truthiness of the decoded value rather than on whether the key exists:So a present key holding a falsy value — an empty string, or
0,falseandnullwhen read withtype: "json"— falls through to the bare-value branch, loses its metadata, and returns a shape the runtime binding only expects for missing keys:Empty-string values are the most common real-world trigger.
This contradicts the contract the existing tests in
packages/miniflare/test/plugins/kv/index.spec.tsalready assert — every present key yields{ value, metadata }and only missing keys yieldnull. The gap was simply that every existing case used a truthy value.The change
Gate the wrapper on entry presence instead of value truthiness.
storage.get()returnsnullonly for a missing key, and a presentKeyValueEntryalways carries avalue: ReadableStream<Uint8Array>, soobj !== nullis the correct — and unambiguous — presence check. Missing keys still return a barenull.The two preceding
obj?.valuetruthiness checks are switched to the same explicit presence check. Those are behaviourally equivalent (a present entry'svaluestream is never null), but reading presence three different ways in one function is what allowed the bug to hide in the first place.Scope / compatibility
withMetadatapath changes shape, and only for present-but-falsy values — which were previously returning the documented-wrong shape.local-explorer'sbulkGetKVValues) uses that path, so it is unaffected.GET /:keyis untouched.Testing
Four tests added to
packages/miniflare/test/plugins/kv/index.spec.ts:0,false,null){ value, metadata }wrapper while a missing key in the same request still returns a barenullThe first three fail on
mainand pass with this change. Fullminiflaresuite: 898 passed. Two unrelated failures (hyperdrive/proxy.spec.tsTLS modes, and theTZ=UTCsubprocess test inindex.spec.ts) reproduce identically on an unmodifiedmainon this Windows machine and are environmental.oxlint --deny-warnings --type-aware,tsc, andoxfmtare all clean.getWithMetadatabehaviour in local dev; no public API or documented behaviour changes.A picture of a cute animal (not mandatory, but encouraged)
🦫