sveltejs/kit · error · HandledHttpError

new HandledHttpError({ status: res.status, message: from JSO

Error message

new HandledHttpError({ status: res.status, message: from JSON body, or 'Internal Error' / 'Not Found' for 404 })

What it means

When a server data request fails, the client reads the JSON error body and throws a HandledHttpError whose status comes from the response and whose message comes from the body — falling back to 'Internal Error', or 'Not Found' for 404. This surfaces server-side +error/+server.js failures to calling code such as load functions or streamed data consumers.

Source

Thrown at packages/kit/src/runtime/client/client.js:3699

	const fetcher = DEV ? dev_fetch : window.fetch;
	const res = await fetcher(data_url.href, {});

	// detect new deployments from the response header
	notify_version(res.headers.get('x-sveltekit-version'));

	if (!res.ok) {
		// if `__data.json` doesn't exist or the server has an internal error,
		// avoid parsing the HTML error page as a JSON
		/** @type {App.Error} */
		let error = { status: res.status, message: 'Internal Error' };

		if (res.headers.get('content-type')?.includes('application/json')) {
			error = { status: res.status, ...(await res.json()) };
		} else if (res.status === 404) {
			error.message = 'Not Found';
		}

		throw new HandledHttpError(error);
	}

	return new Promise((resolve, reject) => {
		process_stream(resolve, res).catch(reject);
	});

	// TODO edge case handling necessary? stream() read fails?
}

/**
 * @param {(value: ServerNodesResponse | ServerRedirectNode) => void} resolve
 * @param {Response} res
 * @returns {Promise<void>}
 */
async function process_stream(resolve, res) {
	const reader = /** @type {ReadableStream<Uint8Array>} */ (res.body).getReader();

	/**

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Fix the underlying server endpoint that returned the non-OK status
  2. Add proper error handling in +server.js/+page.server.js and return typed fails
  3. Inspect res.status in the HandledHttpError to distinguish 404 vs 500 causes
  4. Ensure error responses are JSON so meaningful messages reach the client

Example fix

// before
const data = await fetch('/api/items').then((r) => r.json()); // throws HandledHttpError on 500
// after
try {
  const data = await fetch('/api/items').then((r) => r.json());
} catch (e) {
  console.error(e.status, e.message); // e.g. 404 'Not Found'
  return fallback;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: verify endpoint exists (dev-time check)
async function assertEndpoint(url) {
  const r = await fetch(url, { method: 'HEAD' });
  if (!r.ok) console.warn(`${url} -> ${r.status}`);
}

Type guard

function isHandledHttpError(e) { return e instanceof Error && typeof e.status === 'number'; }

Try / catch

try { const data = await loadThing(); } catch (e) {
  if (typeof e.status === 'number') {
    if (e.status === 404) showNotFound();
    else showServerError(e.status, e.message);
  } else { throw e; }
}

Prevention

When it happens

Trigger: A __data fetch (or stream resource fetch) responds non-OK: a 404 from a missing endpoint, a 500 from a throwing +server.js handler; non-JSON bodies fall back to fixed messages.

Common situations: Endpoint removed or route renamed after deploy; unhandled exceptions in form actions/API routes; API returning HTML error pages (no JSON) so message becomes generic 'Internal Error'.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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