withastro/astro · error · Error

Body size limit exceeded: received more than ${limit} bytes

Error message

Body size limit exceeded: received more than ${limit} bytes

What it means

Thrown by the Node adapter's `limitAsyncIterable` wrapper when the total bytes received from the request body stream exceed the configured limit. The function accumulates `received` across all chunks; once it surpasses `limit`, a plain `Error` is thrown (not an AstroError) with the limit in bytes. This is a DoS protection mechanism for the Node app server.

Source

Thrown at packages/astro/src/core/app/node.ts:487

/**
 * Wraps an async iterable with a size limit. If the total bytes received
 * exceed the limit, an error is thrown.
 */
async function* limitAsyncIterable(
	iterable: AsyncIterable<any>,
	limit: number,
): AsyncGenerator<any> {
	let received = 0;
	for await (const chunk of iterable) {
		const byteLength =
			chunk instanceof Uint8Array
				? chunk.byteLength
				: typeof chunk === 'string'
					? Buffer.byteLength(chunk)
					: 0;
		received += byteLength;
		if (received > limit) {
			throw new Error(`Body size limit exceeded: received more than ${limit} bytes`);
		}
		yield chunk;
	}
}

/**
 * Returns the cleanup function for the AbortController and socket listeners created by `createRequest()`
 * for the NodeJS IncomingMessage. This should only be called directly if the request is not
 * being handled by Astro, i.e. if not calling `writeResponse()` after `createRequest()`.
 * ```js
 * import { createRequest, getAbortControllerCleanup } from 'astro/app/node';
 * import { createServer } from 'node:http';
 *
 * const server = createServer(async (req, res) => {
 *     const request = createRequest(req);
 *     const cleanup = getAbortControllerCleanup(req);
 *     if (cleanup) cleanup();
 *     // can now safely call another handler

View on GitHub (pinned to d081033d5f)

Solutions

  1. Increase the body size limit in your Node adapter/standalone server configuration.
  2. If using `@astrojs/node`, check the adapter's request body limit settings.
  3. Split large uploads into chunks or use a dedicated file upload endpoint.
  4. Compress the request body (gzip/brotli) if the client supports it.
  5. Validate expected payload size on the client before sending.

Example fix

// before — default limit too small for file uploads
import { createHandler } from 'astro/app/node';

// after — configure a higher limit
// In standalone server or custom handler setup, increase the body limit:
// Pass a larger `limit` to the request body reader or configure
// the adapter to accept larger payloads per your server framework docs.
Defensive patterns

Strategy: validation

Validate before calling

function assertBodySize(contentLength: string | null, limit: number) {
  if (contentLength && parseInt(contentLength, 10) > limit) {
    throw new Error(`Request body exceeds ${limit} bytes`);
  }
}

Try / catch

app.post('/upload', async (req, res) => {
  try {
    await readBody(req);
  } catch (e) {
    if (e instanceof Error && e.message.includes('Body size limit exceeded')) {
      res.status(413).json({ error: 'Payload too large' });
      return;
    }
    throw e;
  }
});

Prevention

When it happens

Trigger: A client sends a POST/PUT request whose body (form data, JSON payload, file upload) exceeds the byte limit configured for the Node adapter. The `limitAsyncIterable` generator is wrapping the request's async iterable body, and the cumulative byte count crosses the threshold.

Common situations: Uploading a large file via a form POST. Sending a very large JSON body to an API endpoint. The body size limit is set too low for the application's needs. A client accidentally sends an unbounded stream. Testing with large payloads against a locally running Node adapter.

Related errors


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