{"record":{"id":"117e10849e641908","repo":"vercel-labs/skills","slug":"download-is-larger-than-limits-downloadmaxbytes","errorCode":null,"errorMessage":"Download is larger than ${limits.downloadMaxBytes} bytes. Set SKILLS_DOWNLOAD_MAX_BYTES to override.","messagePattern":"Download is larger than (.+?) bytes\\. Set SKILLS_DOWNLOAD_MAX_BYTES to override\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/download-source.ts","lineNumber":98,"sourceCode":"async function downloadToFile(\n  url: string,\n  targetFile: string,\n  limits: DownloadLimits\n): Promise<void> {\n  const response = await fetch(url, {\n    signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n    redirect: 'follow',\n  });\n\n  if (!response.ok) {\n    throw new Error(`Download failed with HTTP ${response.status}`);\n  }\n\n  const contentLength = response.headers.get('content-length');\n  if (contentLength) {\n    const parsed = Number.parseInt(contentLength, 10);\n    if (Number.isFinite(parsed) && parsed > limits.downloadMaxBytes) {\n      throw new Error(\n        `Download is larger than ${limits.downloadMaxBytes} bytes. Set SKILLS_DOWNLOAD_MAX_BYTES to override.`\n      );\n    }\n  }\n\n  if (!response.body) {\n    throw new Error('Download response has no body');\n  }\n\n  let downloaded = 0;\n  const limitStream = new TransformStream<Uint8Array, Uint8Array>({\n    transform(chunk, controller) {\n      downloaded += chunk.byteLength;\n      if (downloaded > limits.downloadMaxBytes) {\n        throw new Error(\n          `Download is larger than ${limits.downloadMaxBytes} bytes. Set SKILLS_DOWNLOAD_MAX_BYTES to override.`\n        );\n      }","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/vercel-labs/skills/blob/435076e78988e1e6ec40d00b0b1d76bdbbc5419a/src/download-source.ts#L80-L116","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the file size first: curl -sI <url> | grep -i content-length","If the file is trusted and legitimately large, raise the cap: SKILLS_DOWNLOAD_MAX_BYTES=1048576000 skills add <url>","Use a slimmer archive or a git source that fetches only needed paths","Confirm you didn't accidentally point at a full-repo or monorepo snapshot"],"exampleFix":"# before\nskills add https://example.com/all-skills.zip  # Download is larger than max bytes\n\n# after\nSKILLS_DOWNLOAD_MAX_BYTES=1048576000 skills add https://example.com/all-skills.zip","handlingStrategy":"validation","validationCode":"// Compare Content-Length against your budget before calling the API\nasync function assertWithinBudget(url: string, maxBytes: number): Promise<void> {\n  const res = await fetch(url, { method: 'HEAD' });\n  const len = Number(res.headers.get('content-length'));\n  if (Number.isFinite(len) && len > maxBytes) {\n    throw new Error(`Artifact too large: ${len} > ${maxBytes}`);\n  }\n}","typeGuard":"null","tryCatchPattern":"try {\n  await downloadSource(url);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('SKILLS_DOWNLOAD_MAX_BYTES')) {\n    // either raise the env limit or choose a smaller artifact\n  } else throw err;\n}","preventionTips":["Publish slim per-skill archives instead of monolithic bundles","Export SKILLS_DOWNLOAD_MAX_BYTES explicitly in automation scripts"],"tags":["download","limits","content-length","env-var"],"backgroundTag":"resource-limit-exceeded","analyzedSha":"435076e78988e1e6ec40d00b0b1d76bdbbc5419a","analyzedAt":"2026-08-28T17:47:53.369Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}