google-gemini/gemini-cli · error

Download failed: No response body

Error message

Download failed: No response body

What it means

After confirming the HTTP response is OK (response.ok is true), downloadFile() checks that response.body is present. If the server returned a success status without a readable body stream, the download cannot proceed. This is a defensive check for an unusual edge case in the fetch response.

Source

Thrown at packages/cli/src/commands/gemma/setup.ts:84

  } else {
    process.stderr.write(`\r  Downloaded ${formatBytes(downloaded)}`);
  }
}

async function downloadFile(url: string, destPath: string): Promise<void> {
  const tmpPath = destPath + '.downloading';
  if (fs.existsSync(tmpPath)) {
    fs.unlinkSync(tmpPath);
  }

  const response = await fetch(url, { redirect: 'follow' });
  if (!response.ok) {
    throw new Error(
      `Download failed: HTTP ${response.status} ${response.statusText}`,
    );
  }
  if (!response.body) {
    throw new Error('Download failed: No response body');
  }

  const contentLength = response.headers.get('content-length');
  const totalBytes = contentLength ? parseInt(contentLength, 10) : null;
  let downloadedBytes = 0;

  const fileStream = fs.createWriteStream(tmpPath);
  const reader = response.body.getReader();

  try {
    for (;;) {
      const { done, value } = await reader.read();
      if (done) break;
      const writeOk = fileStream.write(value);
      if (!writeOk) {
        await new Promise<void>((resolve) => fileStream.once('drain', resolve));
      }
      downloadedBytes += value.byteLength;

View on GitHub (pinned to 5024443c72)

Solutions

  1. Retry the download — may be transient.
  2. Check proxy, VPN, and CDN configuration for body-stripping behavior.
  3. Try a different network connection to rule out a local proxy issue.
  4. If persistent, the hosting server is likely misconfigured — report the issue.
Defensive patterns

Strategy: retry

Try / catch

async function downloadWithBodyRetry(url: string, dest: string, maxRetries = 3): Promise<void> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      await downloadFile(url, dest);
      return;
    } catch (e) {
      if (e instanceof Error && e.message === 'Download failed: No response body' && attempt < maxRetries) {
        await new Promise((r) => setTimeout(r, 1000 * attempt));
        continue;
      }
      throw e;
    }
  }
}

Prevention

When it happens

Trigger: A server or proxy returns HTTP 200 with a null or absent body stream. This can occur with certain reverse proxy configurations, HTTP/2 edge cases, HEAD-like responses misrouted as GET, or server bugs.

Common situations: Misconfigured reverse proxy stripping the response body; unusual CDN behavior; transparent proxy intercepting and reformatting responses; HTTP/2 protocol quirks.

Related errors


AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12). Data as JSON: /api/errors/3fb834c030c61c6d. Report an issue: GitHub.