{"record":{"id":"16b8437dfb24050c","repo":"upstash/context7","slug":"failed-to-fetch-item-path-fileresponse-statu","errorCode":null,"errorMessage":"Failed to fetch ${item.path}: ${fileResponse.status}","messagePattern":"Failed to fetch (.+?): (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/cli/src/utils/github.ts","lineNumber":286,"sourceCode":"        : \"\";\n    return { files: [], error: `GitHub API error: ${treeData.error}${hint}` };\n  }\n\n  const skillFiles = treeData.tree.filter(\n    (item) => item.type === \"blob\" && item.path.startsWith(skillPath + \"/\")\n  );\n\n  if (skillFiles.length === 0) {\n    return { files: [], error: `No files found in ${skillPath}` };\n  }\n\n  const files: SkillFile[] = [];\n  for (const item of skillFiles) {\n    const rawUrl = `${GITHUB_RAW}/${owner}/${repo}/${branch}/${item.path}`;\n    const fileResponse = await fetch(rawUrl, { headers: ghHeaders });\n\n    if (!fileResponse.ok) {\n      console.warn(`Failed to fetch ${item.path}: ${fileResponse.status}`);\n      continue;\n    }\n\n    const content = await fileResponse.text();\n    const relativePath = item.path.slice(skillPath.length + 1);\n\n    // Reject paths that attempt directory traversal\n    if (relativePath.includes(\"..\")) {\n      console.warn(`Skipping file with unsafe path: ${item.path}`);\n      continue;\n    }\n\n    files.push({\n      path: relativePath,\n      content,\n    });\n  }\n","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/upstash/context7/blob/4416fb855b8f752be735e34f943b5d0762701aad/packages/cli/src/utils/github.ts#L268-L304","documentation":"This warning is emitted by downloadSkillTree while fetching individual skill files from GitHub raw content. When a file's HTTP response is not ok (e.g. 404 or 403), the file is skipped with this message rather than failing the whole download, so the resulting skill tree may be incomplete. It indicates a per-file fetch failure for a path that the GitHub API listed.","triggerScenarios":"Calling downloadSkillTree (via its result caller) when GitHub returns a non-2xx status for `${GITHUB_RAW}/${owner}/${repo}/${branch}/${item.path}` — typically the file was deleted or renamed after the tree listing, the branch/tag is wrong, or a private repo returns 404/403 without auth.","commonSituations":"Pinning a stale branch that no longer contains every file in the tree; fetching from a private repo where raw.githubusercontent.com lacks credentials; rate-limiting (403) from GitHub; a recently moved/renamed skill path.","solutions":["Verify the branch/tag passed to downloadSkillTree actually contains the reported file (check it on GitHub).","Ensure ghHeaders include a valid GitHub token if the repo is private or rate limits are being hit.","Refresh the skillFiles tree listing so it doesn't reference deleted/renamed paths.","Retry the download later if the status was 403/429 (rate limit or transient GitHub issue)."],"exampleFix":"// before\nawait downloadSkillTree({ owner: 'org', repo: 'skills', branch: 'main' });\n// after\nawait downloadSkillTree({ owner: 'org', repo: 'skills', branch: 'main', headers: { Authorization: `Bearer ${GITHUB_TOKEN}` } });","handlingStrategy":"retry","validationCode":"// before download\nconst tree = await fetchTree(owner, repo, branch);\nconst missing = tree.filter(f => !f.sha);\nif (missing.length) console.warn('stale tree entries', missing);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass a GitHub token in ghHeaders to avoid 403 rate limits.","Pin a specific commit SHA instead of a moving branch.","Refresh the tree listing immediately before downloading files.","Collect skipped paths and retry them once before reporting success."],"tags":["network","github","http","fetch"],"backgroundTag":"network-request-failed","analyzedSha":"4416fb855b8f752be735e34f943b5d0762701aad","analyzedAt":"2026-09-16T20:28:07.148Z","contentChangedAt":"2026-09-16T20:28:07.148Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}