Skip to content

miniflare KV bulk getWithMetadata drops metadata for present-but-falsy values (0, false, empty string) #14594

Description

@tsushanth

Description

The miniflare KV bulk-get handler (@POST("/bulk/get")) wraps each present key as { value, metadata }, but the wrap is gated on the truthiness of the value, so present keys holding a falsy value (JSON 0, false, null, or text "") are returned as the bare value and lose their metadata — diverging from the shape the runtime binding expects.

This contradicts the repo's own tested contract (packages/miniflare/test/plugins/kv/index.spec.ts), which asserts every present key in a bulk getWithMetadata yields { value, metadata } and only missing keys yield null. The existing tests only use truthy values, so the falsy case is uncovered. Empty-string values are the most common real trigger.

Steps to reproduce

await env.KV.put("k", "", { metadata: { a: 1 } });
const r = await env.KV.getWithMetadata(["k"]);
// expected: Map { "k" => { value: "", metadata: { a: 1 } } }
// actual:   { "k": "" }  — metadata lost, shape wrong

Root cause

packages/miniflare/src/workers/kv/namespace.worker.ts (processKeyValue): if (val && withMetadata) { return [{ value: val, metadata: … }, size]; } return [val, size]; — the val && gates on value-truthiness instead of key-presence.

Suggested fix

Gate on entry presence rather than value truthiness, e.g. compute const exists = obj?.value != null (or obj !== null) and use if (exists && withMetadata). Missing keys continue to return a bare null; present-but-falsy values keep their { value, metadata } wrapper.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    Untriaged

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions