{"record":{"id":"352ba91afda3f55c","repo":"infiniflow/ragflow","slug":"download-url-not-available-for-file-file-path","errorCode":null,"errorMessage":"Download URL not available for file: ${file.path}","messagePattern":"Download URL not available for file: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/src/pages/skills/components/upload-modal.tsx","lineNumber":509,"sourceCode":"      repo: string,\n      ref: string,\n    ): Promise<File> => {\n      let downloadUrl = file.download_url;\n      const config = PLATFORM_CONFIG[platform];\n\n      // If download_url is not provided, construct raw URL\n      if (!downloadUrl) {\n        if (platform === 'github') {\n          // https://raw.githubusercontent.com/owner/repo/ref/path\n          downloadUrl = `${config.rawBase}/${owner}/${repo}/${ref}/${file.path}`;\n        } else if (platform === 'gitee') {\n          // https://gitee.com/owner/repo/raw/ref/path\n          downloadUrl = `${config.rawBase}/${owner}/${repo}/raw/${ref}/${file.path}`;\n        }\n      }\n\n      if (!downloadUrl) {\n        throw new Error(`Download URL not available for file: ${file.path}`);\n      }\n\n      const response = await fetch(downloadUrl);\n      if (!response.ok) {\n        throw new Error(\n          `Failed to download ${file.path}: ${response.status} ${response.statusText}`,\n        );\n      }\n\n      const blob = await response.blob();\n      const fileName = file.path.split('/').pop() || 'file';\n\n      // Use MIME type from extension if blob.type is empty or generic\n      let fileType = blob.type;\n      if (\n        !fileType ||\n        fileType === 'application/octet-stream' ||\n        fileType === 'text/plain'","sourceCodeStart":491,"sourceCodeEnd":527,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/web/src/pages/skills/components/upload-modal.tsx#L491-L527","documentation":"Raised during file download when no download URL could be determined: the git API listing provided no download_url AND the platform-specific raw URL could not be constructed because the detected platform matched neither 'github' nor 'gitee'. It indicates either an unsupported platform value or a listing entry lacking download_url for a platform without a raw-URL fallback.","triggerScenarios":"parseGitUrl/gitPlatform yields a platform string other than 'github'/'gitee'; a directory entry or submodule in the file list has download_url undefined and the platform branch falls through; ref/path components empty making the constructed URL invalid (though non-empty string still passes).","commonSituations":"New git host support half-added (platform enum extended without a raw URL rule); git submodule entries in the repo tree; API responses from Gitee enterprise endpoints that omit download_url.","solutions":["Confirm the import URL is for github.com or gitee.com — other hosts are not supported","Exclude submodule/directory entries from the file list before download (filter f.type === 'file')","If adding a new platform, add its raw URL construction branch in the download function","Inspect the file entry for a missing download_url via the browser debugger"],"exampleFix":"// before\nif (!downloadUrl) {\n  if (platform === 'github') { ... } else if (platform === 'gitee') { ... }\n}\nif (!downloadUrl) {\n  throw new Error(`Download URL not available for file: ${file.path}`);\n}\n\n// after\nif (!downloadUrl && platform === 'github') {\n  downloadUrl = `${config.rawBase}/${owner}/${repo}/${ref}/${file.path}`;\n} else if (!downloadUrl && platform === 'gitee') {\n  downloadUrl = `${config.rawBase}/${owner}/${repo}/raw/${ref}/${file.path}`;\n}\n// skip entries that are still unresolved (e.g. submodules)\nif (!downloadUrl) continue; // inside the per-file loop","handlingStrategy":"type-guard","validationCode":"const SUPPORTED_PLATFORMS = ['github', 'gitee'] as const;\n\nif (!SUPPORTED_PLATFORMS.includes(platform)) {\n  showWarning(`Platform '${platform}' is not supported for raw downloads`);\n}\n\n// filter entries that can actually be downloaded\nconst downloadable = files.filter(\n  (f) => f.type === 'file' && (f.download_url || platform === 'github' || platform === 'gitee'),\n);","typeGuard":"function hasDownloadPath(f: { download_url?: string; path: string }, platform: string): boolean {\n  if (f.download_url) return true;\n  return platform === 'github' || platform === 'gitee'; // raw URL constructible\n}","tryCatchPattern":"for (const file of files) {\n  try {\n    downloaded.push(await downloadGitFile(platform, owner, repo, ref, file, token));\n  } catch (e) {\n    if (e instanceof Error && e.message.startsWith('Download URL not available')) {\n      continue; // skip unsupported entry (e.g. submodule), keep importing the rest\n    }\n    downloadErrors.push(`${file.path}: ${e instanceof Error ? e.message : e}`);\n  }\n}","preventionTips":["Restrict the platform selector to hosts with raw URL rules implemented","Filter listing entries to type === 'file' before attempting downloads","When adding a new git host, add its raw URL construction in the same change"],"tags":["github-api","download","platform-support","skills","edge-case"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}