withastro/astro · error · ActionError
CONTENT_TOO_LARGE
CONTENT_TOO_LARGE
Error message
Request body exceeds ${bodySizeLimit} bytes What it means
Astro enforces security.actionBodySizeLimit (default 1 MB) on action request bodies. When an incoming request carries a content-length header larger than the configured limit, the size is known before reading, so parseRequestBody rejects immediately with ActionError code CONTENT_TOO_LARGE — the body is never parsed.
Solutions
- Raise the limit in astro.config.mjs: security: { actionBodySizeLimit: 10 * 1024 * 1024 } (10 MB in this example)
- Reduce the payload: strip unneeded fields, paginate, or compress client-side
- Move large uploads to a dedicated server endpoint (src/pages/api/*.ts) which has no action limit, and keep the action for metadata
Example fix
// before — astro.config.mjs defaults (1 MB), payload is 3 MB
// after
export default defineConfig({
security: {
actionBodySizeLimit: 10 * 1024 * 1024, // 10 MB
},
}); Defensive patterns
Strategy: validation
Validate before calling
// check payload size before sending
const LIMIT = 1024 * 1024; // keep in sync with security.actionBodySizeLimit
const body = JSON.stringify(payload);
if (body.length > LIMIT) {
throw new Error(`Payload ${body.length}B exceeds action limit ${LIMIT}B — use an endpoint`);
}
await actions.importData(payload); Try / catch
try {
await actions.importData(payload);
} catch (e) {
if (e instanceof ActionError && e.code === 'CONTENT_TOO_LARGE') {
// split the payload into chunks or move to a dedicated upload endpoint
} else throw e;
} Prevention
- Set security.actionBodySizeLimit explicitly to your real maximum in astro.config.mjs
- Never base64 large files into action payloads — use endpoints or object storage
- Track typical payload sizes in dev to catch drift before production 413s
When it happens
Trigger: POSTing an action payload (JSON or form) whose declared content-length exceeds the limit — e.g. base64-encoded images or large text in a JSON action, or a multipart upload above 1 MB against the default.
Common situations: Adding image/file upload-through-actions features; embedding large generated content (reports, pasted documents) in action inputs; adapters or proxies that inflate the body (compression removed) pushing sizes just over the default.
Related errors
- ActionCalledFromServerError
- ActionCalledFromServerError
- ActionNotFoundError
- ActionsReturnedInvalidDataError
- [astro:actions] `defineAction()` unexpectedly used on the…
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/3a1937d86ce1b46c.
Report an issue: GitHub.
Appendix: source
Thrown at packages/astro/src/actions/runtime/server.ts:267
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 52e6c34790)