sveltejs/kit · error · Error

Data returned from action inside ${route_id} is not serializ

Error message

Data returned from action inside ${route_id} is not serializable. Form actions need to return plain objects or fail(). E.g. return { success: true } or return fail(400, { message: "invalid" });

What it means

Action return values are serialized with devalue and shipped to the client. `try_serialize` caught a devalue failure and detected the returned data is actually a `Response` — e.g. someone used `json(...)` in a form action — which cannot be used as an action result. Form actions must return plain objects or `fail()`.

Source

Thrown at packages/kit/src/runtime/server/page/actions.js:310

export function uneval_action_response(data, route_id) {
	return try_serialize(data, uneval, route_id);
}

/**
 * @param {any} data
 * @param {(data: any) => string} fn
 * @param {string} route_id
 */
function try_serialize(data, fn, route_id) {
	try {
		return fn(data);
	} catch (e) {
		// If we're here, the data could not be serialized with devalue
		const error = /** @type {any} */ (e);

		// if someone tries to use `json()` in their action
		if (data instanceof Response) {
			throw new Error(
				`Data returned from action inside ${route_id} is not serializable. Form actions need to return plain objects or fail(). E.g. return { success: true } or return fail(400, { message: "invalid" });`,
				{ cause: e }
			);
		}

		// if devalue could not serialize a property on the object, etc.
		if ('path' in error) {
			let message = `Data returned from action inside ${route_id} is not serializable: ${error.message}`;
			if (error.path !== '') message += ` (data.${error.path})`;
			throw new Error(message, { cause: e });
		}

		throw error;
	}
}

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Return a plain serializable object instead of `json()`: `return { success: true }`
  2. Use `return fail(status, data)` for error responses
  3. If you truly need a custom Response, use a `+server.js` endpoint, not a form action

Example fix

// before
import { json } from '@sveltejs/kit';
export const actions = { default: async () => json({ ok: true }) };
// after
export const actions = { default: async () => ({ ok: true }) };
Defensive patterns

Strategy: type-guard

Validate before calling

// before returning from an action
if (result instanceof Response) {
  throw new TypeError('Actions must return plain objects or fail(), not Responses');
}

Type guard

/** @returns {result is Record<string, any>} */
function isPlainActionResult(result) {
  return !(result instanceof Response);
}

Prevention

When it happens

Trigger: Returning `json(data)` from a `+page.server.js` action; returning a raw `Response` object from an action; any action data that devalue cannot serialize when it happens to be a Response instance.

Common situations: Copying `+server.js` handler code (where returning `json()` is valid) into a form action; mixing up load/handle code with action code; refactoring an endpoint into an action without changing the return type.

Related errors


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