koala73/worldmonitor · error · WidgetBodyTooLargeError
Widget body too large
Error message
Widget body too large
What it means
readRequestBody for the widget-agent proxy reads the incoming request stream and enforces WIDGET_AGENT_MAX_BODY_BYTES. As soon as the cumulative byte count exceeds the cap it throws WidgetBodyTooLargeError, surfacing as 'Widget body too large'. This protects the upstream widget-agent service from oversized payloads and bounds memory use in the edge function.
Solutions
- Reduce the request payload sent to the widget-agent endpoint below the configured byte cap.
- Chunk or split the work into multiple smaller widget-agent requests.
- If the cap is too low for legitimate workloads, raise WIDGET_AGENT_MAX_BODY_BYTES.
- Strip unnecessary fields/attachments from the payload before sending.
Example fix
// before
await fetch('/api/widget-agent', { method: 'POST', body: JSON.stringify({ html: hugeHtml, ...rest }) });
// after
await fetch('/api/widget-agent', { method: 'POST', body: JSON.stringify({ html: hugeHtml.slice(0, 100_000), ...rest }) }); Defensive patterns
Strategy: validation
Validate before calling
const body = JSON.stringify(payload);
const bytes = new TextEncoder().encode(body).byteLength;
if (bytes > WIDGET_AGENT_MAX_BODY_BYTES) throw new Error(`payload ${bytes}B exceeds limit`); Try / catch
try { return await proxyWidgetAgent(req); } catch (e) { if (e instanceof WidgetBodyTooLargeError) return json(413, { error: 'body exceeds limit' }); throw e; } Prevention
- Measure serialized payload size client-side before POSTing
- Send assets by reference (URL) instead of inline base64
- Split large widget jobs into multiple requests
- Keep the byte cap documented next to the client integration
When it happens
Trigger: POSTing a request body larger than WIDGET_AGENT_MAX_BODY_BYTES to the widget-agent proxy endpoint (proxyWidgetAgent -> readRequestBody).
Common situations: Clients embedding large HTML/JSON payloads in widget generation requests; uploading base64 assets inline; retry loops that keep re-sending an oversized body.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- body-too-large
- ${err.message}
- Malformed command: expected an array whose first element is…
- Airport delay filters are not supported
- Airport delay page_size must be 0
AI-assisted analysis of koala73/worldmonitor@e586b8b4b8 (2026-09-22).
Data as JSON: /api/errors/d1848fbcca0fa482.
Report an issue: GitHub.
Appendix: source
Thrown at api/widget-agent.ts:115
this.name = 'WidgetBodyTooLargeError';
}
}
async function readRequestBody(req: Request): Promise<string> {
if (!req.body) return '';
const reader = req.body.getReader();
let timer: ReturnType<typeof setTimeout> | undefined;
try {
return await Promise.race([
(async () => {
const decoder = new TextDecoder();
let total = 0;
let text = '';
while (true) {
const { done, value } = await reader.read();
if (done) return text + decoder.decode();
total += value.byteLength;
if (total > WIDGET_AGENT_MAX_BODY_BYTES) throw new WidgetBodyTooLargeError();
text += decoder.decode(value, { stream: true });
}
})(),
new Promise<never>((_, reject) => {
timer = setTimeout(() => reject(new Error('widget-agent body read timeout')), WIDGET_AGENT_BODY_TIMEOUT_MS);
}),
]);
} finally {
clearTimeout(timer);
// Do not let a stalled producer's cancellation hold the response open.
void reader.cancel().catch(() => {});
reader.releaseLock();
}
}
async function hasValidWorldMonitorKey(key: string): Promise<boolean> {
return timingSafeIncludes(key, WORLDMONITOR_VALID_KEYS);
}View on GitHub (pinned to e586b8b4b8)