docs(cloudflare): fix env bindings access pattern for Nitro v3 (breaking change)#4064
docs(cloudflare): fix env bindings access pattern for Nitro v3 (breaking change)#4064ruan-cat wants to merge 2 commits intonitrojs:mainfrom
Conversation
Update cloudflare.md to show the correct v3 pattern (event.req.runtime.cloudflare.env) and add a breaking change warning. Add migration section to 99.migration.md.
|
@ruan-cat is attempting to deploy a commit to the Nitro Team on Vercel. A member of the Team first needs to authorize it. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds documentation updates instructing migration from Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@pi0 Can you check and review it? I was discovered within the nitro v3 version, with the aid of AI event. The I hope to merge into the main branch soon. This change is documentation only and adds more detail to the already patchy nitro v3 documentation. |
RihanArfan
left a comment
There was a problem hiding this comment.
Great docs fix — the v2 → v3 binding path change definitely needed documenting. I've been looking at this from the code side too, and there's a related issue: the Wrangler dev proxy plugin (src/presets/cloudflare/runtime/plugin.dev.ts) still sets bindings on the old event.req.context.cloudflare path instead of event.req.runtime.cloudflare. This means the old pattern appears to work in local dev (which is why the warnings below mention it), but fails in production.
The fix is straightforward — update the dev plugin to match the production augmentReq behavior from _module-handler.ts:
nitroApp.hooks.hook("request", async (event) => {
(event.req as any).cf = proxy.cf;
event.req.runtime ??= { name: "cloudflare" };
event.req.runtime.cloudflare = {
...event.req.runtime.cloudflare,
env: proxy.env,
context: proxy.ctx,
};
event.req.waitUntil = proxy.ctx.waitUntil.bind(proxy.ctx);
});With that fix applied, the "may still appear to work in local dev" caveats in the docs become inaccurate — hence the inline suggestions below to simplify the warning text.
I've verified this works end-to-end: set up a playground with the cloudflare-module preset, a wrangler.jsonc with a KV binding, and a test route using event.req.runtime.cloudflare.env — KV read/write works correctly through the dev emulation.
|
|
||
| ::warning | ||
| **Nitro v3 Breaking Change:** The `event.context.cloudflare.env` pattern from Nitro v2 no longer works in production. Use `event.req.runtime.cloudflare.env` instead. The old pattern may still appear to work in local dev (via the Wrangler proxy plugin) but will be `undefined` in production deployments. |
There was a problem hiding this comment.
Same here — with the dev plugin fix, the local dev caveat no longer applies. Can simplify to:
| ::warning | |
| **Nitro v3 Breaking Change:** The `event.context.cloudflare.env` pattern from Nitro v2 no longer works in production. Use `event.req.runtime.cloudflare.env` instead. The old pattern may still appear to work in local dev (via the Wrangler proxy plugin) but will be `undefined` in production deployments. | |
| **Nitro v3 Breaking Change:** The `event.context.cloudflare.env` pattern from Nitro v2 has been changed to `event.req.runtime.cloudflare.env` in Nitro v3. | |
| :: |
Co-authored-by: Rihan Arfan <me@file.properties>
|
Thanks for the review and the detailed explanation! I have applied your suggestion. (I'm new to this process, but the 'Commit suggestion' feature is really convenient!) |
| defineHandler(async (event) => { | ||
| const { cloudflare } = event.context | ||
| const stmt = await cloudflare.env.MY_D1.prepare('SELECT id FROM table') | ||
| // Nitro v3: access Cloudflare bindings via event.req.runtime.cloudflare.env |
There was a problem hiding this comment.
I don't think we need the v3 code comment since these docs are for v3 rather than the migration guide.
|
Thank you for your changes @ruan-cat. Please could you update the wrangler dev plugin in |
I have enabled allow maintainers to edit. You can start editing. |
Summary
This PR fixes outdated documentation for accessing Cloudflare Worker environment variables and bindings in Nitro v3. The existing docs still show the Nitro v2 pattern (
event.context.cloudflare.env), which does not work in production with Nitro v3. This has been a source of confusion for developers migrating from v2 to v3.Problem
The current documentation in
docs/2.deploy/20.providers/cloudflare.mdshows:This pattern (
event.context.cloudflare.env) was correct in Nitro v2 but fails silently in Nitro v3 production deployments —event.context.cloudflareisundefinedat runtime, so accessing.envon it throws or returns nothing.Additionally, the migration guide (
docs/1.docs/99.migration.md) has no mention of this breaking change, leaving developers without guidance when upgrading.Root Cause
In Nitro v3, the underlying server layer switched from H3/unenv to srvx. As a result, the Cloudflare preset's production runtime entry now attaches the Cloudflare context to the request's runtime object rather than the event context.
The relevant code is in
src/presets/cloudflare/runtime/_module-handler.ts:The
augmentReq()function is called in the productionfetchhandler:This means in Nitro v3, the correct path to access Cloudflare bindings is:
Why does it seem to work in local dev?
The dev plugin (
src/presets/cloudflare/runtime/plugin.dev.ts) still populatesevent.req.context.cloudflarefor local development via the Wrangler proxy. This creates a confusing discrepancy: the old pattern works locally but fails in production.Evidence
Debug Endpoint
A diagnostic API endpoint was written to probe all possible paths for Cloudflare env access in Nitro v3:
Source:
server/api/debug-env.get.tsKey probe from that file:
Live Reproducible Demo
The endpoint is deployed to Cloudflare Workers using Nitro v3:
URL: https://01s-11.ruan-cat.com/api/debug-env
This live endpoint confirms that:
req.runtime.cloudflare.envcontains the environment variables and bindings ✓event.context.cloudflareisundefinedin production ✗Changes
This PR modifies documentation only — no source code changes.
docs/2.deploy/20.providers/cloudflare.mdevent.req.runtime.cloudflare.env)::warningcallout explaining the breaking change from v2docs/1.docs/99.migration.mddiffmigration example showing the old v2 pattern vs. the new v3 patternTesting
The fix can be verified by deploying a Nitro v3 app to Cloudflare Workers and confirming that
event.req.runtime.cloudflare.envreturns the expected bindings. The live demo at https://01s-11.ruan-cat.com/api/debug-env serves as a reproducible test case.