vercel-labs/skills · error · Error

Download is larger than ${limits.downloadMaxBytes} bytes. Se

Error message

Download is larger than ${limits.downloadMaxBytes} bytes. Set SKILLS_DOWNLOAD_MAX_BYTES to override.

What it means

Before streaming the body, downloadToFile checks the Content-Length header against limits.downloadMaxBytes and throws if the server-declared size already exceeds the cap. This is an early exit so a huge file is never downloaded at all. The limit is tunable via SKILLS_DOWNLOAD_MAX_BYTES.

Source

Thrown at src/download-source.ts:98

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>({
    transform(chunk, controller) {
      downloaded += chunk.byteLength;
      if (downloaded > limits.downloadMaxBytes) {
        throw new Error(
          `Download is larger than ${limits.downloadMaxBytes} bytes. Set SKILLS_DOWNLOAD_MAX_BYTES to override.`
        );
      }

View on GitHub (pinned to 435076e789)

Solutions

  1. Check the file size first: curl -sI <url> | grep -i content-length
  2. If the file is trusted and legitimately large, raise the cap: SKILLS_DOWNLOAD_MAX_BYTES=1048576000 skills add <url>
  3. Use a slimmer archive or a git source that fetches only needed paths
  4. Confirm you didn't accidentally point at a full-repo or monorepo snapshot

Example fix

# before
skills add https://example.com/all-skills.zip  # Download is larger than max bytes

# after
SKILLS_DOWNLOAD_MAX_BYTES=1048576000 skills add https://example.com/all-skills.zip
Defensive patterns

Strategy: validation

Validate before calling

// Compare Content-Length against your budget before calling the API
async function assertWithinBudget(url: string, maxBytes: number): Promise<void> {
  const res = await fetch(url, { method: 'HEAD' });
  const len = Number(res.headers.get('content-length'));
  if (Number.isFinite(len) && len > maxBytes) {
    throw new Error(`Artifact too large: ${len} > ${maxBytes}`);
  }
}

Type guard

null

Try / catch

try {
  await downloadSource(url);
} catch (err) {
  if (err instanceof Error && err.message.includes('SKILLS_DOWNLOAD_MAX_BYTES')) {
    // either raise the env limit or choose a smaller artifact
  } else throw err;
}

Prevention

When it happens

Trigger: Downloading a URL whose Content-Length exceeds the configured download budget — e.g. a release asset of several hundred MB when the cap is lower, or a user-lowered SKILLS_DOWNLOAD_MAX_BYTES.

Common situations: Skill archives that bundle heavy assets, mirrors serving full repo snapshots, or environments where the default budget is too small for the artifact being fetched.

Related errors


AI-assisted analysis of vercel-labs/skills@435076e789 (2026-08-28). Data as JSON: /api/errors/117e10849e641908. Report an issue: GitHub.