{"record":{"id":"8dd53d34c2eaad0e","repo":"Mintplex-Labs/anything-llm","slug":"failed-to-download-file","errorCode":null,"errorMessage":"Failed to download file","messagePattern":"Failed to download file","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/src/pages/GeneralSettings/ScheduledJobs/components/GeneratedFileCard.jsx","lineNumber":89,"sourceCode":"  return {\n    ...fileDisplayInfo,\n    type: fileDisplayInfo.label(t),\n  };\n}\n\n// Card representing a file generated by a job run. Streams the file from\n// the storage API on download via dynamic import of file-saver.\nexport default function GeneratedFileCard({ file }) {\n  const { t } = useTranslation();\n  const [downloading, setDownloading] = useState(false);\n  const { badge, bg, text, type } = getFileDisplayInfo(file.filename, t);\n\n  const handleDownload = async () => {\n    if (downloading || !file.storageFilename) return;\n    setDownloading(true);\n    try {\n      const blob = await StorageFiles.download(file.storageFilename);\n      if (!blob) throw new Error(\"Failed to download file\");\n      const { saveAs } = await import(\"file-saver\");\n      saveAs(blob, file.filename || file.storageFilename);\n    } catch {\n      showToast(t(\"scheduledJobs.file.downloadFailed\"), \"error\");\n    } finally {\n      setDownloading(false);\n    }\n  };\n\n  return (\n    <div className=\"flex items-center justify-between bg-zinc-800 light:bg-slate-100 rounded-lg p-3\">\n      <div className=\"flex items-center gap-3 min-w-0\">\n        <div\n          className={`${bg} ${text} rounded-lg flex items-center justify-center shrink-0 h-10 w-10 text-xs font-semibold`}\n        >\n          {badge}\n        </div>\n        <div className=\"flex flex-col min-w-0\">","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/3aec848f2885144aa8f1e53b9731a04310d5d558/frontend/src/pages/GeneralSettings/ScheduledJobs/components/GeneratedFileCard.jsx#L71-L107","documentation":"GeneratedFileCard streams a scheduled-job artifact via StorageFiles.download(file.storageFilename). If the call returns a falsy blob (missing file, expired signed URL, auth failure) or throws, the catch shows the localized 'download failed' toast. The inner throw new Error('Failed to download file') is the explicit guard for a falsy blob.","triggerScenarios":"Downloading a file whose storageFilename was already removed by retention cleanup; a 401 on the storage route from an expired session; the storage backend (local disk or S3) unreachable; the file deleted between listing job artifacts and clicking download.","commonSituations":"Old job artifact pruned by cleanup but still listed in the UI; storage driver misconfigured; session token expired while the jobs page stayed open.","solutions":["Retry once — transient storage/network errors often clear immediately.","Check the Network tab for the storage file request status: 401 → re-login, 404 → file gone, 500 → storage backend issue.","Verify the file still exists in the job's storage directory (or bucket) if 404.","Confirm storage provider credentials/config if downloads consistently fail."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"function isDownloadable(file) {\n  return !!file && typeof file.storageFilename === 'string' && file.storageFilename.length > 0;\n}\n// Before starting:\nif (!isDownloadable(file)) { showToast('File is no longer available.', 'warning'); return; }","typeGuard":null,"tryCatchPattern":"async function downloadArtifact(storageFilename, filename, tries = 2) {\n  for (let attempt = 1; attempt <= tries; attempt++) {\n    try {\n      const blob = await StorageFiles.download(storageFilename);\n      if (!blob) throw new Error('Empty response');\n      const { saveAs } = await import('file-saver');\n      return saveAs(blob, filename || storageFilename);\n    } catch (e) {\n      if (attempt === tries) throw e; // transient storage/network errors often clear on retry\n      await new Promise((r) => setTimeout(r, 500 * attempt));\n    }\n  }\n}","preventionTips":["Disable the download button for artifacts older than the retention window, or prune them from the list.","Keep the jobs page session fresh so storage requests do not 401 after long idle.","Distinguish 404 (file gone — stop retrying) from 5xx/network (retry once) in the handler."],"tags":["file-download","scheduled-jobs","storage","blob"],"backgroundTag":"file-download-failed","analyzedSha":"3aec848f2885144aa8f1e53b9731a04310d5d558","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}