Hmbown/CodeWhale · error

Release response exceeds size limit

Error message

Release response exceeds size limit

What it means

boundedJson enforces a byte ceiling while streaming the release response; as soon as accumulated bytes exceed `limit`, it throws "Release response exceeds size limit" (cancelling the reader in finally). This bounds memory usage so a huge or malicious response cannot exhaust the worker.

Solutions

  1. Raise the `limit` argument to accommodate the actual manifest size, if the growth is legitimate.
  2. Verify the URL returns the small JSON manifest, not an HTML error page — check content-type and the beginning of the body.
  3. Add a check on content-type/content-length before reading and reject non-JSON responses early.
  4. Keep the limit as a guard: if the response genuinely should be small, investigate why it ballooned rather than disabling the check.

Example fix

// before
const json = await boundedJson(res, 64 * 1024);

// after (verify type, then use an adequate limit)
const ct = res.headers.get('content-type') ?? '';
if (!ct.includes('application/json')) throw new Error('expected JSON manifest');
const json = await boundedJson(res, 256 * 1024);
Defensive patterns

Strategy: validation

Validate before calling

const len = Number(res.headers.get('content-length') ?? '0');
if (len > LIMIT) throw new Error(`release response too large: ${len} > ${LIMIT}`);
if (!(res.headers.get('content-type') ?? '').includes('json')) throw new Error('release endpoint returned non-JSON');

Try / catch

try {
  return await boundedJson(res, LIMIT);
} catch (e) {
  if (e.message === 'Release response exceeds size limit') {
    log.error('release payload too large — possible error page or oversized manifest', { url: res.url });
    return cachedRelease();
  }
  throw e;
}

Prevention

When it happens

Trigger: A release manifest or asset download larger than the configured limit (e.g. an unexpectedly large API response or an HTML error page served instead of a small JSON manifest).

Common situations: GitHub API returning an oversized response; limit tuned too low for a legitimate larger manifest; a proxy error page (multi-hundred-KB HTML) masquerading as the release endpoint; limit mismatch after moving to a richer release format.

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


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

Appendix: source

Thrown at web/lib/computer-use-release.ts:101

    url: `${COMPUTER_USE_REPO}/releases/tag/v${version}`,
    downloadUrl: zip.browser_download_url as string,
    receiptUrl: assets.receipt.browser_download_url as string,
    verification: "github-digest",
    ...(dmg ? { dmg } : {}),
  };
}

async function boundedJson(response: Response, limit: number): Promise<unknown> {
  if (!response.body) throw new Error("Missing release response");
  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let length = 0, text = "";
  try {
    for (;;) {
      const { done, value } = await reader.read();
      if (done) break;
      length += value.byteLength;
      if (length > limit) throw new Error("Release response exceeds size limit");
      text += decoder.decode(value, { stream: true });
    }
    return JSON.parse(text + decoder.decode());
  } finally { await reader.cancel(); reader.releaseLock(); }
}

const WEB_HEADERS = { "User-Agent": "codewhale-web" };

/** GET a release web endpoint, following at most three 302s and only onto GitHub's release hosts over https. */
async function fetchReleaseWeb(url: string): Promise<Response> {
  for (let hops = 0; ; hops++) {
    const response = await fetch(url, { redirect: "manual", headers: WEB_HEADERS, signal: AbortSignal.timeout(5000) });
    if (![301, 302, 307, 308].includes(response.status)) return response;
    await response.body?.cancel();
    const location = response.headers.get("location");
    if (!location) throw new Error("Release redirect without a location");
    const target = new URL(location, url);
    if (hops >= 3 || target.protocol !== "https:" || !RELEASE_HOSTS.has(target.hostname)) {

View on GitHub (pinned to 433685b202)