{"record":{"id":"1f692eb295055d0f","repo":"infiniflow/ragflow","slug":"no-files-could-be-downloaded-errors-n-downloade","errorCode":null,"errorMessage":"No files could be downloaded. Errors:\\n${downloadErrors.slice(0, 3).join('\\n')}","messagePattern":"No files could be downloaded\\. Errors:\\\\n(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/src/pages/skills/components/upload-modal.tsx","lineNumber":638,"sourceCode":"\n        try {\n          const downloadedFile = await downloadGitFile(\n            gitPlatform,\n            file,\n            owner,\n            repo,\n            ref,\n          );\n          downloadedFiles.push(downloadedFile);\n        } catch (err) {\n          const errorMsg = err instanceof Error ? err.message : String(err);\n          console.warn(`Failed to download ${file.path}:`, err);\n          downloadErrors.push(`${file.path}: ${errorMsg}`);\n        }\n      }\n\n      if (downloadedFiles.length === 0) {\n        throw new Error(\n          `No files could be downloaded. Errors:\\n${downloadErrors.slice(0, 3).join('\\n')}`,\n        );\n      }\n\n      // 3. Validate skill format\n      setGitProgress('Validating skill format...');\n\n      const validation = await validateSkillFormat(downloadedFiles);\n\n      if (!validation.valid) {\n        setGitValidationStatus('invalid');\n        const errorKey = `skills.validation.${validation.error}`;\n        const errorMessage = t(errorKey) || validation.error;\n        const details = validation.details ? `: ${validation.details}` : '';\n        setGitValidationMessage(`${errorMessage}${details}`);\n        setGitImporting(false);\n        setGitProgress('');\n        return;","sourceCodeStart":620,"sourceCodeEnd":656,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/web/src/pages/skills/components/upload-modal.tsx#L620-L656","documentation":"Raised when every attempted file download failed, so downloadedFiles is empty. The error aggregates up to three per-file failure messages (path + error) captured in the catch of the download loop, exposing the underlying causes — typically the 'Failed to download ...' or 'Download URL not available ...' errors from the download helper.","triggerScenarios":"All listed files fail download: raw endpoint rate-limited/403, private repo without authenticated raw fetch, files removed since listing, or all entries lacking download_url (submodules). The slice(0,3) messages reveal which.","commonSituations":"Bulk import of a large repo hitting rate limits mid-run; private repository where API listing works with token but raw fetches do not; network with blocked raw.githubusercontent.com.","solutions":["Read the embedded per-file errors — they name the file and the underlying cause (status code or missing URL)","For 403/rate errors, add a token or wait and retry; reduce the number of files imported at once","For 'Download URL not available', exclude non-file entries from the listing before download","Verify raw.githubusercontent.com / gitee raw endpoints are reachable from the browser network"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// pre-filter to entries known to be downloadable before starting\nconst targets = gitFiles.filter(\n  (f) => f.type === 'file' && !isOversized(f) && (f.download_url || canBuildRawUrl(platform)),\n);\nif (targets.length === 0) {\n  showWarning('No downloadable files in this repository path');\n  return;\n}","typeGuard":"function isDownloadFailure(e: unknown): e is Error {\n  return e instanceof Error && /^Failed to download|Download URL not available/.test(e.message);\n}","tryCatchPattern":"const downloadedFiles = [];\nconst downloadErrors: string[] = [];\nfor (const file of filteredGitFiles) {\n  try {\n    downloadedFiles.push(await downloadGitFile(platform, owner, repo, ref, file, gitToken || undefined));\n  } catch (err) {\n    if (isTransient(err)) await backoffRetry(file); // salvage what we can\n    downloadErrors.push(`${file.path}: ${err instanceof Error ? err.message : String(err)}`);\n  }\n}\nif (downloadedFiles.length === 0) {\n  setGitValidationStatus('invalid');\n  setGitValidationMessage(`No files could be downloaded. Errors:\\n${downloadErrors.slice(0, 3).join('\\n')}`);\n}","preventionTips":["Add a token before bulk imports so 403/rate failures do not kill every download","Show partial-success results (downloadedFiles.length > 0) instead of failing the whole import","Limit concurrency and add backoff for raw endpoint downloads"],"tags":["download","aggregate-error","github-api","network","skills"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}