sveltejs/kit · error · Error
exports is not available in dev mode
Error message
exports is not available in dev mode
What it means
The `exports` binding of the cloudflare:workers virtual module is only meaningful in the deployed/preview Workers runtime where the Worker's actual exports exist. In `vite dev` there is no built-and-deployed Worker to export, so the adapter substitutes a Proxy whose get trap unconditionally throws. Accessing any property on `exports` during dev therefore fails with this message.
Source
Thrown at packages/adapter-cloudflare/src/virtual-cloudflare-workers.js:115
if (!proxy) {
throw new Error(`Cannot access cloudflare:workers in a prerenderable route`);
}
return als.run(newEnv, fn);
}
/** @type {Module['withEnvAndExports']} */
export function withEnvAndExports(newEnv, _, fn) {
if (!proxy) {
throw new Error(`Cannot access cloudflare:workers in a prerenderable route`);
}
return als.run(newEnv, fn);
}
// no-ops
export const exports = new Proxy(
{},
{
get() {
throw new Error('exports is not available in dev mode');
},
has() {
throw new Error('exports is not available in dev mode');
}
}
);
/** @type {Module['waitUntil']} */
export function waitUntil() {}
/** @type {Module['cache']} */
export const cache = {
purge() {
return Promise.resolve({ success: true, errors: [] });
}
};
class Span {
get isTraced() {
return false;
}View on GitHub (pinned to 03f1687fe6)
Solutions
- Remove the `exports` usage from SvelteKit server code — use service bindings configured in wrangler.jsonc instead of self-referencing exports.
- Guard the access so it only runs in the deployed runtime: if (import.meta.env.DEV) skip or mock the exports usage.
- Test the exports-dependent path with `wrangler dev` on a built worker instead of `vite dev`.
- Provide a dev-mode stub: wrap the import in a module that returns a mock during dev.
Example fix
// before
import { exports } from 'cloudflare:workers';
const worker = exports.default;
// after
import { env } from 'cloudflare:workers'; // use bindings instead, or guard:
let worker;
if (!import.meta.env.DEV) {
const { exports } = await import('cloudflare:workers');
worker = exports.default;
} Defensive patterns
Strategy: fallback
Validate before calling
if (import.meta.env.DEV) {
console.warn('cloudflare:workers exports is unavailable in dev; skipping');
} Type guard
function exportsAvailable() {
return typeof import.meta !== 'undefined' && !import.meta.env.DEV;
} Try / catch
try {
const { exports } = await import('cloudflare:workers');
return exports.default;
} catch (e) {
if (e.message.includes('not available in dev mode')) return devStubWorker;
throw e;
} Prevention
- Prefer service bindings over self-referencing `exports` from cloudflare:workers.
- Gate any `exports` usage behind `!import.meta.env.DEV`.
- Test exports-dependent code paths with `wrangler dev` on a built worker.
- Document dev-mode limitations when sharing Worker utility code into SvelteKit.
When it happens
Trigger: Importing { exports } from 'cloudflare:workers' in dev mode and reading any property of it (e.g. exports.default, named worker exports) from a load function, endpoint, or module-scope code running under `vite dev`.
Common situations: Code written for a Workers-only project uses `exports` to self-reference the Worker (e.g. for worker-to-worker RPC via CloudflareServiceBinding) and is reused inside a SvelteKit dev session; accessing `exports.default` to call the current worker.
Related errors
- read(...) failed: could not fetch ${url} (${response.status}
- Cloudflare Pages' _routes.json should be configured from the
- You must remove all `site` keys in ${config_path}. Consult h
- You must specify the `assets.directory` key in ${config_path
- You must specify the `assets.binding` key in ${config_path}
AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02).
Data as JSON: /api/errors/b68affb2716a343e.
Report an issue: GitHub.