sveltejs/kit · error · Error

Cannot access cloudflare:workers in a prerenderable route

Error message

Cannot access cloudflare:workers in a prerenderable route

What it means

The virtual `cloudflare:workers` module exposes `env` (bindings like KV, D1, R2) only when running as a Cloudflare Worker with a real platform object (`globalThis.__sveltekit_cloudflare_platform`). During prerendering at build time there is no worker runtime, so reading any property of `env` throws. It is a deliberate guard against silently returning undefined bindings for prerendered pages.

Source

Thrown at packages/adapter-cloudflare/src/virtual-cloudflare-workers.js:18

import { AsyncLocalStorage } from 'node:async_hooks';

const als = new AsyncLocalStorage();

const proxy = globalThis.__sveltekit_cloudflare_platform;

function get_current_env() {
	return als.getStore() ?? proxy.env;
}

/** @typedef {typeof import('@cloudflare/workers-types').CloudflareWorkersModule} Module */

export const env = new Proxy(
	{},
	{
		get(_, prop) {
			if (!proxy) {
				throw new Error(`Cannot access cloudflare:workers in a prerenderable route`);
			}
			const inner = get_current_env();
			if (inner) {
				return Reflect.get(inner, prop);
			}
			return undefined;
		},

		set(_, prop, newValue) {
			if (!proxy) {
				throw new Error(`Cannot access cloudflare:workers in a prerenderable route`);
			}
			const inner = get_current_env();
			if (inner) {
				return Reflect.set(inner, prop, newValue);
			}
			return true;
		},

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Set `export const prerender = false` for routes that need Cloudflare bindings, or exclude them via `prerender.entries`/handle.
  2. Move `env` access inside request-time code (load functions that only run on the server at request time, API routes) rather than prerendered paths.
  3. Guard access: check `building`/`prerender` context or lazily access `env` only when the binding is actually needed at request time.
  4. Mock `cloudflare:workers` via a Vite alias or `@sveltejs/kit`'s mocking for the prerender/build phase if the value is static.

Example fix

// before (prerendered +settings page)
import { env } from 'cloudflare:workers';
export const load = () => ({ kv: await env.MY_KV.get('k') });
// after
import { env } from 'cloudflare:workers';
export const prerender = false;
export const load = () => ({ kv: await env.MY_KV.get('k') });
Defensive patterns

Strategy: try-catch

Validate before calling

import { building } from '$app/environment';
// ensure this route is not prerendered if it reads env
export const prerender = false;

Type guard

import { building } from '$app/environment';
function canAccessWorkerEnv() {
  return !building && typeof globalThis.__sveltekit_cloudflare_platform !== 'undefined';
}

Try / catch

import { env } from 'cloudflare:workers';
let value;
try {
  value = env.MY_KV;
} catch (e) {
  if (e.message.includes('prerenderable route')) {
    value = undefined; // fallback for prerender/build context
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Prerendering a route (e.g. `export const prerender = true` or prerender-all config) whose code — including load functions, hooks, or imported modules — evaluates `env.<binding>` from `cloudflare:workers` while `proxy` is null.

Common situations: Enabling `prerender` on a page that uses D1/KV bindings; a shared library accessing `env` at module top level gets executed during prerender; SSR fallback code paths run during build prerender.

Related errors


AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02). Data as JSON: /api/errors/0f509a2229c2d4ba. Report an issue: GitHub.