withastro/astro · error · BodySizeLimitError

Request body exceeds the configured limit of ${limit} bytes

Error message

Request body exceeds the configured limit of ${limit} bytes

What it means

readBodyWithLimit() rejected the request early because the Content-Length header exceeds the configured byte limit. This is the fast-path check used by Actions (security.actionBodySizeLimit) and Server Islands (security.serverIslandBodySizeLimit) to deny oversized payloads before streaming.

Source

Thrown at packages/astro/src/core/request-body.ts:19

/**
 * Shared utility for reading request bodies with a size limit.
 * Used by both Actions and Server Islands to enforce `security.actionBodySizeLimit`
 * and `security.serverIslandBodySizeLimit` respectively.
 */

/**
 * Read the request body as a `Uint8Array`, enforcing a maximum size limit.
 * Checks the `Content-Length` header for early rejection, then streams the body
 * and tracks bytes received.
 *
 * @throws {BodySizeLimitError} if the body exceeds the configured limit
 */
export async function readBodyWithLimit(request: Request, limit: number): Promise<Uint8Array> {
	const contentLengthHeader = request.headers.get('content-length');
	if (contentLengthHeader) {
		const contentLength = Number.parseInt(contentLengthHeader, 10);
		if (Number.isFinite(contentLength) && contentLength > limit) {
			throw new BodySizeLimitError(limit);
		}
	}

	if (!request.body) return new Uint8Array();
	const reader = request.body.getReader();
	const chunks: Uint8Array[] = [];
	let received = 0;
	while (true) {
		const { done, value } = await reader.read();
		if (done) break;
		if (value) {
			received += value.byteLength;
			if (received > limit) {
				throw new BodySizeLimitError(limit);
			}
			chunks.push(value);
		}
	}

View on GitHub (pinned to d081033d5f)

Solutions

  1. Raise the relevant limit in astro.config: security.actionBodySizeLimit or security.serverIslandBodySizeLimit.
  2. Reduce the payload size on the client (compress, chunk uploads, offload large data to a separate endpoint).
  3. If the value is unexpected, inspect what the client is sending — a runaway payload may indicate a bug.
  4. Ensure the limit unit matches bytes (not kilobytes).

Example fix

// before — astro.config.mjs
export default defineConfig({
  security: { actionBodySizeLimit: 100 } // 100 bytes, too small
});

// after
export default defineConfig({
  security: { actionBodySizeLimit: 1_000_000 } // ~1 MB
});
Defensive patterns

Strategy: validation

Validate before calling

function withinContentLength(request: Request, limit: number): boolean {
  const cl = Number.parseInt(request.headers.get('content-length') ?? '', 10);
  return Number.isFinite(cl) ? cl <= limit : true;
}
// client-side: check before sending
if (!withinContentLength(request, LIMIT)) return errorResponse();

Try / catch

try {
  await readBodyWithLimit(request, limit);
} catch (e) {
  if (e instanceof BodySizeLimitError) return new Response('Payload too large', { status: 413 });
  throw e;
}

Prevention

When it happens

Trigger: A POST/fetch to an Action or Server Island whose Content-Length is greater than the configured limit; large JSON/form payloads; misconfigured low limit; client sending unexpectedly big bodies.

Common situations: Default body size limits too low for legitimate payloads (e.g. large form, base64 image); actions receiving big JSON; server islands receiving large props; testing with oversized fixtures.

Related errors


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