payloadcms/payload · error · Error
Failed to download: ${url}
Error message
Failed to download: ${url} What it means
Thrown by downloadTarStream after fetch() resolves against the payloadcms/payload codeload tar.gz URL but res.body is falsy. This guards the stream pipeline (tar extraction) which needs readable bytes. The check does NOT verify res.ok, so HTTP error statuses with a body slip past; only a missing/empty body triggers it.
Source
Thrown at packages/create-payload-app/src/lib/download-example.ts:42
debugLog(`Codeload url: ${url}`)
debugLog(`Filter: ${filter}`)
}
await pipeline(
await downloadTarStream(url),
x({
cwd: projectDir,
filter: (p) => p.includes(filter),
strip: 2 + example.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
- Verify network access to https://codeload.github.com/payloadcms/payload/tar.gz/<branch> (curl -I) and disable/inspect any HTTP proxy.
- Re-run with --debug to print the exact codeload URL and confirm the branchOrTag resolved from example.url is correct.
- Confirm the referenced branch/tag still exists in the payloadcms/payload repo; switch to a stable tag if it was removed.
- Upgrade Node to a version with a compliant global fetch (>=18 with undici) and ensure no polyfill overrides it.
Example fix
// before
const res = await fetch(url)
if (!res.body) {
throw new Error(`Failed to download: ${url}`)
}
// after — also surface HTTP failures clearly
const res = await fetch(url)
if (!res.ok) {
throw new Error(`Failed to download (HTTP ${res.status}): ${url}`)
}
if (!res.body) {
throw new Error(`Failed to download (empty body): ${url}`)
} Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight the codeload URL reachability before invoking create-payload-app
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}`)
}
}
await assertCodeloadReachable('latest') Try / catch
// Wrap the create-payload-app invocation and retry on transient bodyless responses
async function downloadWithRetry(url: string, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
const res = await fetch(url)
if (res.ok && res.body) return res.body
if (i === attempts - 1) throw new Error(`Failed to download: ${url}`)
} catch (e) {
if (i === attempts - 1) throw e
}
await new Promise((r) => setTimeout(r, 500 * (i + 1)))
}
} Prevention
- Run create-payload-app in an environment with direct access to codeload.github.com.
- Use --debug to surface the resolved codeload URL before the failure.
- Pin example.url to a stable tag rather than a branch that may be deleted.
When it happens
Trigger: Running create-payload-app with --example where the GitHub codeload endpoint returns a response with no body (opaque response, redirect to a bodyless 3xx, a corporate proxy stripping bodies, or a non-compliant global fetch shim). Also reachable in runtimes whose fetch returns null body for non-2xx.
Common situations: Behind a corporate proxy or firewall that intercepts codeload.github.com; offline/cached CI with a patched fetch; running an old Node version where undici fetch behaves differently; the example's branch/tag (example.url#<ref>) was deleted so codeload returns an empty body.
Related errors
- Failed to download: ${url}
- Failed to update Payload packages
- No version or tag "${version}" found for package: ${packageN
- Invalid template given
- Invalid database type given. Valid types are: ${Object.value
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/d93e57f9a874b686.
Report an issue: GitHub.