payloadcms/payload · error · Error

Failed to download: ${url}

Error message

Failed to download: ${url}

What it means

Identical guard to download-example but for the --template flow. downloadTarStream fetches the payloadcms/payload codeload tarball and throws if res.body is absent. Like the example variant, it does not check res.ok; only a bodyless response triggers this exact line.

Source

Thrown at packages/create-payload-app/src/lib/download-template.ts:42

    debugLog(`Codeload url: ${url}`)
    debugLog(`Filter: ${filter}`)
  }

  await pipeline(
    await downloadTarStream(url),
    x({
      cwd: projectDir,
      filter: (p) => p.includes(filter),
      strip: 2 + template.name.split('/').length,
    }),
  )
}

async function downloadTarStream(url: string) {
  const res = await fetch(url)

  if (!res.body) {
    throw new Error(`Failed to download: ${url}`)
  }

  return Readable.from(res.body as unknown as NodeJS.ReadableStream)
}

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Confirm reachability of https://codeload.github.com/payloadcms/payload/tar.gz/<branch> (curl -I) and check proxy env (HTTP_PROXY/HTTPS_PROXY).
  2. Re-run with --debug to log the resolved codeload URL and filter string, confirming template.url and branchOrTag.
  3. Ensure the referenced branch/tag exists; pin to a known tag (e.g. latest) if the ref was removed.
  4. Use a Node version with a compliant global fetch and remove conflicting fetch polyfills.

Example fix

// before
const res = await fetch(url)
if (!res.body) {
  throw new Error(`Failed to download: ${url}`)
}

// after
const res = await fetch(url)
if (!res.ok || !res.body) {
  throw new Error(`Failed to download (status ${res.status}): ${url}`)
}
Defensive patterns

Strategy: retry

Validate before calling

import { request } from 'undici'

async function assertCodeloadReachable(branchOrTag: string) {
  const url = `https://codeload.github.com/payloadcms/payload/tar.gz/${branchOrTag}`
  const res = await request(url, { method: 'HEAD' })
  if (res.statusCode >= 400) {
    throw new Error(`codeload unreachable for ${branchOrTag}: HTTP ${res.statusCode}`)
  }
}

Try / catch

async function downloadWithRetry(url: string, attempts = 3) {
  for (let i = 0; i < attempts; i++) {
    const res = await fetch(url)
    if (res.ok && res.body) return res.body
    if (i === attempts - 1) throw new Error(`Failed to download: ${url}`)
    await new Promise((r) => setTimeout(r, 500 * (i + 1)))
  }
}

Prevention

When it happens

Trigger: Running create-payload-app with --template where codeload returns a response without a body: proxy interception, redirect chain ending in a bodyless response, custom fetch shim, or a deleted/renamed template path producing a bodyless error.

Common situations: Corporate proxy blocking codeload.github.com; CI with cached/patched fetch; template.url#<ref> pointing at a removed branch/tag; running on a Node runtime whose fetch returns null body for non-2xx.

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/57c4e45d2594d41d. Report an issue: GitHub.