withastro/astro · error · ActionError

CONTENT_TOO_LARGE

CONTENT_TOO_LARGE

Error message

Request body exceeds ${bodySizeLimit} bytes

What it means

parseRequestBody reads the Content-Length header; if the declared body size is greater than the configured bodySizeLimit, the request is rejected before the body is read, with ActionError code CONTENT_TOO_LARGE (HTTP 413).

Source

Thrown at packages/astro/src/actions/runtime/server.ts:266

	if (ctx.routePattern === ACTION_RPC_ROUTE_PATTERN) {
		return { from: 'rpc', name: ctx.url.pathname.replace(/^.*\/_actions\//, '') } as const;
	}
	const queryParam = ctx.url.searchParams.get(ACTION_QUERY_PARAMS.actionName);
	if (queryParam) {
		return { from: 'form', name: queryParam } as const;
	}
	return undefined;
}

async function parseRequestBody(request: Request, bodySizeLimit: number) {
	const contentType = request.headers.get('content-type');
	const contentLengthHeader = request.headers.get('content-length');
	const contentLength = contentLengthHeader ? Number.parseInt(contentLengthHeader, 10) : undefined;
	const hasContentLength = typeof contentLength === 'number' && Number.isFinite(contentLength);

	if (!contentType) return undefined;
	if (hasContentLength && contentLength > bodySizeLimit) {
		throw new ActionError({
			code: 'CONTENT_TOO_LARGE',
			message: `Request body exceeds ${bodySizeLimit} bytes`,
		});
	}
	try {
		if (hasContentType(contentType, formContentTypes)) {
			if (!hasContentLength) {
				const body = await readBodyWithLimit(request.clone(), bodySizeLimit);
				const formRequest = new Request(request.url, {
					method: request.method,
					headers: request.headers,
					body: toArrayBuffer(body),
				});
				return await formRequest.formData();
			}
			return await request.clone().formData();
		}
		if (hasContentType(contentType, ['application/json'])) {

View on GitHub (pinned to d081033d5f)

Solutions

  1. Raise bodySizeLimit for the action/server config if larger payloads are legitimate.
  2. Reduce the payload size (paginate, compress, or split the request).
  3. Route large uploads through a dedicated file-upload endpoint or object storage instead of an action.

Example fix

// before - default limit rejects a 2MB JSON body
// astro.config / action config
export default defineConfig({
  // ...
});
// after - raise the limit where the action/server is configured
// (set bodySizeLimit to a value above your max payload, e.g. 3MB)
Defensive patterns

Strategy: validation

Validate before calling

// Reject oversized payloads before sending, based on a known limit.
const MAX = 1024 * 1024; // mirror the configured bodySizeLimit
const size = new Blob([JSON.stringify(payload)]).size;
if (size > MAX) throw new Error(`Payload ${size}B exceeds the ${MAX}B limit`);

Try / catch

try {
  await actions.upload(payload);
} catch (e) {
  if (e instanceof ActionError && e.code === 'CONTENT_TOO_LARGE') {
    // ask user to reduce size, or route to a file endpoint
  } else throw e;
}

Prevention

When it happens

Trigger: An action request whose Content-Length exceeds the configured bodySizeLimit (the default cap applies when none is set).

Common situations: Uploading a large JSON payload or base64 file to a JSON action; increasing payload size without raising the limit; clients/proxies that report an accurate large Content-Length.

Related errors


AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12). Data as JSON: /api/errors/3a1937d86ce1b46c. Report an issue: GitHub.