vercel-labs/skills · error · Error
Download failed with HTTP ${response.status}
Error message
Download failed with HTTP ${response.status} What it means
downloadToFile issues a fetch with redirect:'follow' and a timeout, and throws when response.ok is false — any HTTP status outside 2xx aborts the download before it starts. The status code is embedded in the message, so a 404 means the URL is wrong, 403/401 means auth or rate limiting, and 5xx means the origin failed.
Source
Thrown at src/download-source.ts:91
if (state.bytes > limits.extractMaxBytes) {
throw new ArchiveValidationError(
`Archive extracts to more than ${limits.extractMaxBytes} bytes. Set SKILLS_EXTRACT_MAX_BYTES to override.`
);
}
}
async function downloadToFile(
url: string,
targetFile: string,
limits: DownloadLimits
): Promise<void> {
const response = await fetch(url, {
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
redirect: 'follow',
});
if (!response.ok) {
throw new Error(`Download failed with HTTP ${response.status}`);
}
const contentLength = response.headers.get('content-length');
if (contentLength) {
const parsed = Number.parseInt(contentLength, 10);
if (Number.isFinite(parsed) && parsed > limits.downloadMaxBytes) {
throw new Error(
`Download is larger than ${limits.downloadMaxBytes} bytes. Set SKILLS_DOWNLOAD_MAX_BYTES to override.`
);
}
}
if (!response.body) {
throw new Error('Download response has no body');
}
let downloaded = 0;
const limitStream = new TransformStream<Uint8Array, Uint8Array>({View on GitHub (pinned to 435076e789)
Solutions
- curl -I the URL to see the actual status and confirm it's reachable
- Fix the URL (correct tag/release/branch) or make the repo/asset public
- For private GitHub resources, export GITHUB_TOKEN or GH_TOKEN before running
- If rate-limited (403/429), wait or supply a token; retry with backoff in scripts
Example fix
# before skills add https://github.com/acme/skills/archive/refs/heads/main.zip # HTTP 404 # after curl -I https://github.com/acme/skills/archive/refs/heads/main.zip # check skills add acme/skills # install from git source instead
Defensive patterns
Strategy: retry
Validate before calling
// Probe the URL before downloading
async function assertDownloadable(url: string): Promise<void> {
const res = await fetch(url, { method: 'HEAD' });
if (!res.ok) throw new Error(`URL not downloadable: HTTP ${res.status}`);
} Type guard
null
Try / catch
for (let attempt = 1; attempt <= 3; attempt++) {
try {
return await downloadSource(url);
} catch (err) {
const msg = err instanceof Error ? err.message : '';
if (!/^Download failed with HTTP \d+$/.test(msg) || attempt === 3) throw err;
await new Promise(r => setTimeout(r, attempt * 1000));
}
} Prevention
- Pin URLs to immutable release tags/SHAs, not moving branches
- Set GITHUB_TOKEN/GH_TOKEN in CI to avoid 403 rate limits
When it happens
Trigger: Calling downloadSource with a URL that returns a non-2xx status: deleted GitHub release asset (404), private repo without a token (403/401), rate-limited API (403/429), or an expired pre-signed URL.
Common situations: Typos or stale URLs pointing to moved/renamed releases, GitHub rate limits hit in CI, private repositories downloaded without GITHUB_TOKEN/GH_TOKEN set, or link rot in documentation.
Related errors
- Download response has no body
- Downloaded URL is empty
- Download is larger than ${limits.downloadMaxBytes} bytes. Se
- Archive contains unsafe path: ${entryPath}
- Downloaded URL is not a valid SKILL.md file or supported arc
AI-assisted analysis of vercel-labs/skills@435076e789 (2026-08-28).
Data as JSON: /api/errors/245a320be4124b47.
Report an issue: GitHub.