[Local Dev] Cannot access KV from Cloudflare Pages using wrangler

Hello there,

I’m giving a try to Cloudflare Pages. To do so, I’ve started from the cloudflare-pages preset using Remix.

I’m now trying to get a access to one of my KV namespace. I’ve figured out that the default npm run dev:wrangler initially set to:

cross-env NODE_ENV=development wrangler pages dev ./public

should be changed to:

cross-env NODE_ENV=development wrangler pages dev ./public --kv MYNAMESPACE

Now that I’m doing so, I can clearly see MYNAMESPACE being passed to the context in my Remix route, but when I try to invoke .get() on it, it always returns null values. Here’s the invocation code.

import {json, LoaderFunction} from "@remix-run/cloudflare";

export const loader: LoaderFunction = async ({context}) => {
  const {value} = await context.MYNAMESPACE.get('key1');
  console.log(value); // Always displaying `null`
  return json({value});
};

My initial thought was that the wrangler CLI was incorrectly authenticated. However, by running:

npx cross-env NODE_ENV=development wrangler kv:namespace list

I can correctly list my namespaces.

Would anyone notice what I’m doing incorrectly here?

Thank you very much in advance.

Assuming that context is the one that Functions passes to requests, bindings will exist under the env object of context like the normal Workers API.

export async function onRequest(context) {
  // Contents of context object
  const {
    request, // same as existing Worker API
    env, // same as existing Worker API
    params, // if filename includes [id] or [[path]]
    waitUntil, // same as ctx.waitUntil in existing Worker API
    next, // used for middleware or to fetch assets
    data, // arbitrary space for passing data between middlewares
  } = context;

  return new Response("Hello, world!");
}

I’d expect it to be context.env.MYNAMESPACE.get, or accessed like async ({env}) then env.MYNAMESPACE.get in your arrow function.

Hello @KianNH and thanks for your quick answer.

Sadly no, the context is correct here. In pure Cloudflare Worker context, I think you’d be right. But in the context of that cloudflare-pages Remix preset, the parameter of the LoaderFunction is directly holding a context field to which MYNAMESPACE is attached, as well as an ASSETS property. I was able to confirm by adding a logging statement in my code:

export const loader: LoaderFunction = async ({context}) => {
  console.log(JSON.stringify(context)); // Displays `{"MYNAMESPACE":{},"ASSETS":{}}`
  const {value} = await context.env.MYNAMESPACE.get('key1');
  console.log(value); // Always displaying `null`
  return json({value});
};

You’re getting this as a string, you can’t destruct a string. So, this is expected.

If you’re expecting a JSON as the value then change this to get('key1', 'json');
otherwise, just change this to be const value =

Hello @Walshy and thanks for your quick answer.

This was indeed a serious mistake on my end. Thanks for noticing and sorry for the noise about it. I confirm that I’ve changed but sadly, I get the same result. Here’s the full updated snippet, commented with the respective logging outputs:

export const loader: LoaderFunction = async ({context}) => {
  console.log(JSON.stringify(context)); // Displays `{"MYNAMESPACE":{},"ASSETS":{}}`
  const value = await context.MYNAMESPACE.get('key1');
  console.log(value); // Displays `null`
  return json({value});
};

I confirm that MYNAMESPACE exists and I’ve created a key-value pair such as key1=value1 from my Cloudflare dashboard.

I didn’t read the full thread ok, local != remote. So, local dev uses local storage, it doesn’t ping Cloudflare’s API to get it.

So, unless you created the key locally, it won’t exist. If you pushed this and tested on your site, you’d get the expected result.

Thanks for answering @Walshy. I’ve indeed misunderstood the use of the --kv option of wrangler pages dev: I thought it was supposed to locally bind a real Cloudflare KV to our server, not to create a local one. Thanks for answering.

Candid feedback: it would be nice to include the possibility to bind to a real Cloudflare KV, for instance when the --local false option will be supported.

Thanks again!

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.