Cloudflare KV namespace doesn't bind
Asked Answered
W

2

5

Ran wrangler dev and it doesn't seem to bind Worker KV:

ERROR in /src/handler.ts
./src/handler.ts 16:8-17
[tsl] ERROR in /src/handler.ts(16,9)
      TS2304: Cannot find name 'generalKV'.

Here is handler.ts:

async function postHandler(request: Request): Promise<Response> {
  let content = JSON.stringify(await request.json());
  await generalKV.put([Date.now().toString()], JSON.stringify(content));
  return new Response(content);
}

wrangler.toml:

name = "general-assignment"
type = "javascript"
account_id = "<id>"
workers_dev = true
compatibility_date = "2021-11-01"
kv_namespaces = [ 
    { binding = "generalKV", id = "<id>", preview_id = "<id>" }
]

Some suggests change kv_namespaces to kv-namespaces, but it doesn't work for me. Please inform me if I missed anything else.

Watch answered 1/11, 2021 at 5:51 Comment(2)
The error doesn't seem like it's from Wrangler or Workers, but from Typescript or some typescript related tool (tsl). It seems like you need to tell your compiler that it can expect generalKV to be available at runtime, so that it doesn't complain about it being undefined during compilation.Haversack
@Haversack Sounds reasonable, could you elaborate on how to let compiler expect generalKV to be available, since the documents says a global variable will be created after binding.Watch
S
14

For readers that come to this question via Google and use Wrangler v2 and get this error:

Uncaught (in promise) ReferenceError: MY_KV is not defined

The tutorials and examples neglect a second parameter (and a third parameter). This second parameter holds the environment. You can use and bind to kv with these steps:

# Create the KV namespaces
wrangler kv:namespace create "MY_KV" &&\
wrangler kv:namespace create "MY_KV" --preview

wrangler complains if there is no preview KV, so create them both. Next, create a kv_namespaces array entry and duplicate the preview_id in the default (dev) section (denoted as yyyy below).

# wrangler.toml
name = "worker"
main = "src/index.js"
compatibility_date = "2022-04-14"
account_id = "...."
workers_dev = true

routes = [
    "exmample.com/*"
]

# Duplicate preview_id to id
kv_namespaces = [
    { binding = "MY_KV", preview_id = "yyyy", id = "yyyy" }
]

# Run `wrangler publish --env production` when happy
[env.production]
kv_namespaces = [
    { binding = "MY_KV", id = "xxxx" }
]

You can then bind to kv like so:

# index.js
export default {
  async fetch(request, env) {
  ...
  const someKV = env.MY_KV.get("some-key");
  ...
  }
Scratchboard answered 17/4, 2022 at 0:5 Comment(2)
As always... a nice little bug. Without "preview_id", the binding won't add. Thanks for this.Broome
@Broome was stuck for so long on this thank you so much haha it was preview idGreek
G
0

Did you already manually create the KV namespace on Cloudflare? I don't believe it creates them dynamically from the binding setup in worker (yet).

Documentation for creating via Wrangler -

https://developers.cloudflare.com/workers/cli-wrangler/commands#create

Gould answered 1/11, 2021 at 12:28 Comment(3)
Thanks for reply! Yes I already created them; I tried creating KV namespace from both CLI and web, and I can see them on my Worker KV. But still it doesn't bind.Watch
You might want to also take a look at your typescript setup to have it match this - github.com/cloudflare/workers-types Specifically the bindings section might be what's missing?Gould
Seems like all that I missed is the declaration in the bindings.d.ts, it works now, thank you so much!Watch

© 2022 - 2024 — McMap. All rights reserved.