sveltejs/kit · error · Error
Cannot use relative URL (${info}) with global fetch — use `e
Error message
Cannot use relative URL (${info}) with global fetch — use `event.fetch` instead: https://svelte.dev/docs/kit/web-standards#fetch-apis What it means
In dev, SvelteKit patches `globalThis.fetch` to catch a common mistake: calling global `fetch` with a relative URL (e.g. `fetch('/api/data')`). Relative URLs are invalid for global fetch because there is no request context to resolve them against; inside server code you must use `event.fetch`, which resolves relative URLs against the current request.
Source
Thrown at packages/kit/src/exports/vite/dev/index.js:67
/** @type {AsyncLocalStorage<{ event: RequestEvent, config: any, prerender: PrerenderOption }>} */
const async_local_storage = new AsyncLocalStorage();
globalThis.__SVELTEKIT_TRACK__ = (label) => {
const context = async_local_storage.getStore();
if (!context || context.prerender === true) return;
check_feature(
/** @type {string} */ (context.event.route.id),
context.config,
label,
svelte_config.adapter
);
};
const fetch = globalThis.fetch;
globalThis.fetch = (info, init) => {
if (typeof info === 'string' && !SCHEME.test(info)) {
throw new Error(
`Cannot use relative URL (${info}) with global fetch — use \`event.fetch\` instead: https://svelte.dev/docs/kit/web-standards#fetch-apis`
);
}
return fetch(info, init);
};
write_tsconfig(svelte_config, root);
/** @type {ManifestData} */
let manifest_data;
/** @type {SSRManifest} */
let manifest;
/** @type {Error | null} */
let manifest_error = null;
const runner = get_runner(vite, vite_dev_server);View on GitHub (pinned to 03f1687fe6)
Solutions
- Use `event.fetch` (or `fetch` from the load/action/`RequestEvent` context) instead of global fetch
- Prefix the URL with an absolute origin, e.g. `fetch(url.origin + '/api/data')` using `event.url`
- Pass the event/fetch into shared helper functions so relative URLs resolve correctly
- Restructure to call internal functions directly instead of fetching your own API
Example fix
// before
export async function load() {
const res = await fetch('/api/data');
}
// after
export async function load({ fetch }) {
const res = await fetch('/api/data');
} Defensive patterns
Strategy: type-guard
Validate before calling
function assertAbsoluteUrl(url) {
if (/^\/[^^]*|^\?/.test(url)) {
throw new TypeError(`Use event.fetch for relative URLs: ${url}`);
}
} Type guard
function isAbsoluteUrl(url) {
return typeof url !== 'string' || !!SCHEME_LIKE.test(url) || URL.canParse(url) && new URL(url).origin !== 'null';
} Try / catch
try {
const res = await globalFetch('/api/data');
} catch (err) {
if (/relative URL.*global fetch/.test(err.message)) {
console.error('Switch to event.fetch in server code');
}
throw err;
} Prevention
- Always destructure `fetch` from load/action/event context in server code
- Lint against bare `fetch(` in server-only directories
- Pass fetch explicitly into shared helper modules
- Use absolute origins when you must call an external service from server code
When it happens
Trigger: Any server-side code (load function without event.fetch, +server.ts handler, hooks, instrumentation) calling `fetch('/path')` with a string lacking a scheme during `vite dev`.
Common situations: Code copied from client components into server load; shared data-fetching modules that use global fetch; unit-tested fetch wrappers that worked with a mocked base URL.
Related errors
- Cannot call `fetch` eagerly during server-side rendering wit
- ${node.server_id}: Calling `event.fetch(...)` in a promise h
- Cannot prerender a +server file with ${BODY_DEPENDENT_METHOD
- ${manifest_data.params} does not export `params` from `defin
- Could not find node for ${url}
AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02).
Data as JSON: /api/errors/0894256b00bcd235.
Report an issue: GitHub.