Hmbown/CodeWhale · error · FormBodyError

${cause.message}

Error message

${cause.message}

What it means

readBoundedUrlEncodedForm wraps BodyReadError thrown by readBoundedBody into FormBodyError, reusing its HTTP status and message (hence the dynamic "${cause.message}"). Non-BodyReadError causes are rethrown unchanged.

Solutions

  1. Read cause.message to identify the underlying failure (invalid Content-Length vs payload too large vs read failure).
  2. If the message is "payload too large", shrink the body or raise the maxBytes limit at the call site.
  3. If the message is "invalid Content-Length", fix the client's header; for "body read failed", retry the request.

Example fix

// before
const res = await fetch(url, { method: "POST", body: hugeBody });
// after
if (new TextEncoder().encode(bodyString).byteLength > MAX_BYTES) throw new Error("body exceeds limit");
const res = await fetch(url, { method: "POST", body: bodyString });
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const form = await readBoundedUrlEncodedForm(request, MAX);
} catch (err) {
  if (err instanceof FormBodyError) {
    return new Response(err.message, { status: err.status });
  }
  throw err; // non-body errors propagate unchanged
}

Prevention

When it happens

Trigger: The form body read failed inside readBoundedBody: invalid Content-Length (400), payload too large (413), or a body read failure (400) — then surfaced to the caller as FormBodyError with that message.

Common situations: Oversized form posts to admin routes; malformed Content-Length from custom clients; aborted/failed streams. The visible message is the underlying cause, so fix that cause.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/e3729d4e3ac44f1b. Report an issue: GitHub.

Appendix: source

Thrown at web/lib/bounded-form.ts:26

    super(message);
    this.name = "FormBodyError";
  }
}

export async function readBoundedUrlEncodedForm(
  request: Request,
  maxBytes: number
): Promise<URLSearchParams> {
  const mediaType = request.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
  if (mediaType !== "application/x-www-form-urlencoded") {
    throw new FormBodyError(415, "expected application/x-www-form-urlencoded");
  }

  try {
    const bytes = await readBoundedBody(request, maxBytes);
    return new URLSearchParams(new TextDecoder().decode(bytes));
  } catch (cause) {
    if (cause instanceof BodyReadError) throw new FormBodyError(cause.status, cause.message);
    throw cause;
  }
}

View on GitHub (pinned to 433685b202)