sveltejs/kit · error · Error

Cannot access event.url.hash. Consider using `page.url.hash`

Error message

Cannot access event.url.hash. Consider using `page.url.hash` inside a component instead

What it means

Server-side `event.url` in SvelteKit is a URL whose `hash` property is redefined to throw, because the URL fragment is never sent to the server — the server simply cannot know it. Accessing `event.url.hash` in server code (load functions, hooks, endpoints) therefore throws immediately, with a message pointing to `page.url.hash` in components where the client-side value is available.

Source

Thrown at packages/kit/src/utils/url.js:187

	}

	if ((DEV || !BROWSER) && !allow_hash) {
		disable_hash(tracked);
	}

	return tracked;
}

/**
 * Disallow access to `url.hash` on the server and in `load`
 * @param {URL} url
 */
function disable_hash(url) {
	allow_nodejs_console_log(url);

	Object.defineProperty(url, 'hash', {
		get() {
			throw new Error(
				'Cannot access event.url.hash. Consider using `page.url.hash` inside a component instead'
			);
		}
	});
}

/**
 * Disallow access to `url.search` and `url.searchParams` during prerendering
 * @param {URL} url
 */
export function disable_search(url) {
	allow_nodejs_console_log(url);

	for (const property of ['search', 'searchParams']) {
		Object.defineProperty(url, property, {
			get() {
				throw new Error(`Cannot access url.${property} on a page with prerendering enabled`);
			}

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Move the hash-dependent logic into a component/universal load using `page.url.hash` from `$app/stores`/`$app/state`
  2. Drop the hash on the server — it is always absent from requests, so use `event.url.pathname + event.url.search`
  3. Guard with `browser` (from `$app/environment`) when code runs in both environments

Example fix

// before (+page.server.ts)
const full = event.url.href; // or event.url.hash
// after (+page.svelte.ts / component)
import { page } from '$app/state';
const hash = page.url.hash; // client only; server never sees the fragment
Defensive patterns

Strategy: try-catch

Validate before calling

import { browser } from '$app/environment';
if (!browser) {
	// never read .hash on server-side event.url
	console.assert(!('hashAccess' in plan), 'logic must not rely on url.hash server-side');
}

Type guard

function canReadHash(url) {
	try {
		void url.hash;
		return true;
	} catch {
		return false;
	}
}

Try / catch

let hash = '';
try {
	hash = event.url.hash;
} catch {
	// fragment never reaches the server; fall back to pathname + search
	const url = event.url.pathname + event.url.search;
}

Prevention

When it happens

Trigger: Reading `event.url.hash` (directly or via destructuring/logging) inside `+page.server.ts`/`+server.ts` load functions, server hooks (`handle`, `locals`), or `getRequestEvent` context on the server.

Common situations: Logging the full URL server-side (`console.log(event.url.href)` still works, but explicit `.hash` access throws); porting client code that reads `page.url.hash` into a server module; building canonical URLs and including hash defensively; generic URL-manipulation helpers shared between server and client.

Related errors


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