sveltejs/kit · warning

To use an async `handleError` hook to handle errors that occ

Error message

To use an async `handleError` hook to handle errors that occur during rendering, you must enable `compilerOptions.experimental.async` in the SvelteKit plugin of your Vite config. The returned error has been replaced with a generic object

What it means

SvelteKit calls the user's `handleError` hook when rendering errors. If the hook is async (returns a Promise) but async Svelte support is not enabled, the result cannot be awaited and is discarded/replaced with a generic object, with this warning. It prevents unhandled rejections from the user's async hook.

Source

Thrown at packages/kit/src/runtime/server/errors.js:99

	function merge(body) {
		return { ...fallback, ...body };
	}

	// TODO 4.0 await this, rather than handling the non-Promise case
	let result;
	try {
		const input = { ...caught, event };
		if (__SVELTEKIT_DEV__) add_deprecated_handle_error_properties(input, fallback);

		result = with_request_store({ event, state }, () => hooks.handleError(input));
	} catch (hook_error) {
		log_handle_error_hook_failure(error, hook_error);
		return { status: fallback.status, message: 'Internal Error' };
	}

	if (result instanceof Promise) {
		if (!__SVELTEKIT_SUPPORTS_ASYNC__ && state.is_in_render) {
			console.warn(
				`To use an async \`handleError\` hook to handle errors that occur during rendering, you must enable \`compilerOptions.experimental.async\` in the SvelteKit plugin of your Vite config. The returned error has been replaced with a generic object`
			);

			// we're discarding the result, but we still need to prevent an unhandled
			// rejection if the user's async `handleError` hook rejects
			result.catch((hook_error) => log_handle_error_hook_failure(error, hook_error));

			return {
				status: fallback.status,
				message: 'Internal Error'
			};
		}

		return result.then(merge, (hook_error) => {
			log_handle_error_hook_failure(error, hook_error);
			return { status: fallback.status, message: 'Internal Error' };
		});
	}

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Enable the experimental async compiler option in vite.config: `sveltekit({ compilerOptions: { experimental: { async: true } } })`
  2. Make `handleError` synchronous, or fire-and-forget async work with explicit `.catch` handling
  3. Upgrade Svelte/SvelteKit so async support is stable and enabled by default

Example fix

// vite.config.js before
sveltekit()
// after
sveltekit({ compilerOptions: { experimental: { async: true } } })
Defensive patterns

Strategy: try-catch

Validate before calling

// in hooks.server.js, prefer sync hook unless async is enabled
const isAsyncHook = handleError.constructor.name === 'AsyncFunction';
if (isAsyncHook) console.warn('Enable compilerOptions.experimental.async or make handleError sync');

Try / catch

// keep async work from becoming unhandled rejections
try {
  const r = handleError(error, event);
  if (r instanceof Promise) r.catch((e) => console.error('hook failed', e));
} catch (e) {
  console.error('hook failed', e);
}

Prevention

When it happens

Trigger: An async `handleError` hook in hooks.server.js runs during rendering while `__SVELTEKIT_SUPPORTS_ASYNC__` is false and the error originated in render state; `compilerOptions.experimental.async` is not enabled in the SvelteKit Vite plugin options.

Common situations: Upgrading to async Svelte components without opting in via the compiler flag; logging errors to an external service with `await fetch` inside handleError; mixing Svelte 4-style sync assumptions with Svelte 5 async rendering.

Related errors


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