Mintplex-Labs/anything-llm · warning · Error
Failed to download file
Error message
Failed to download file
What it means
Thrown by StorageFiles.download when the GET to /api/agent-skills/generated-files/{storageFilename} returns a non-2xx status. The request carries a Bearer token from localStorage via baseHeaders(), so a missing/expired token yields 401/403 and trips this guard. The .catch() swallows it and the function resolves to null, so the caller observes a missing download rather than a thrown exception.
Source
Thrown at frontend/src/models/files.js:16
import { API_BASE } from "@/utils/constants";
import { baseHeaders } from "@/utils/request";
const StorageFiles = {
/**
* Download a file from the server
* @param {string} filename - The filename to download
* @returns {Promise<Blob|null>}
*/
download: async function (storageFilename) {
return await fetch(
`${API_BASE}/agent-skills/generated-files/${encodeURIComponent(storageFilename)}`,
{ headers: baseHeaders() }
)
.then((res) => {
if (!res.ok) throw new Error("Failed to download file");
return res.blob();
})
.catch((e) => {
console.error("Download failed:", e);
return null;
});
},
/**
* Fetch a generated image as a Blob. The serve endpoint is auth-protected, so
* we cannot use the URL directly as an <img> src - callers create an object URL.
* @param {string} storageFilename - The image filename to fetch
* @returns {Promise<Blob|null>}
*/
image: async function (storageFilename) {
return await fetch(
`${API_BASE}/image-generation/generated-images/${encodeURIComponent(storageFilename)}`,
{ headers: baseHeaders() }View on GitHub (pinned to 526360e320)
Solutions
- Confirm baseHeaders() sends a non-null Authorization by checking localStorage AUTH_TOKEN before calling.
- Open the failing URL in DevTools Network tab and read the response status and body.
- Verify storageFilename matches an entry returned by the agent-skills listing endpoint (typo/path traversal is blocked by encodeURIComponent).
- Check server logs for the /agent-skills/generated-files route to confirm the file physically exists in its storage root.
Example fix
// before
const blob = await StorageFiles.download(name); // null on failure, silent
if (!blob) return; // no user feedback
// after
const blob = await StorageFiles.download(name);
if (!blob) {
showToast("File is no longer available.");
return;
} Defensive patterns
Strategy: validation
Validate before calling
function canDownload(storageFilename) {
if (typeof storageFilename !== "string" || storageFilename.trim() === "") return false;
if (!window.localStorage.getItem("anythingllm_authToken")) return false;
return true;
}
// if (!canDownload(name)) skip the call Type guard
/** @param {any} r @returns {r is Blob} */
function isBlob(r) { return r instanceof Blob; } Try / catch
// Library already catches and returns null — guard the return value.
const blob = await StorageFiles.download(name);
if (!isBlob(blob)) { /* show 'file unavailable' */ } Prevention
- Always encodeURIComponent the filename when building URLs yourself (the lib already does).
- Null-check the resolved value before creating an object URL.
- Revoke object URLs after use to avoid leaks.
When it happens
Trigger: Calling StorageFiles.download("report.pdf") when storageFilename does not exist on disk (404), when localStorage AUTH_TOKEN is absent or expired (401/403), when the agent-skills storage path is misconfigured on the server, or when the generated file was garbage-collected from a non-persistent volume.
Common situations: The agent skill that produced the file ran in a different container/instance than the one serving downloads; the file was written to ephemeral storage and lost on redeploy; the user clicked a stale download link from a previous session after their token expired.
Related errors
- Could not fetch local files.
- Failed to sync Confluence page content. ${reason}
- Failed to sync GitHub file content. ${reason}
- Failed to sync GitLab file content. ${reason}
- Failed to sync Gitea file content. ${reason}
AI-assisted analysis of Mintplex-Labs/anything-llm@526360e320 (2026-08-13).
Data as JSON: /api/errors/282ef0f9f981c0c5.
Report an issue: GitHub.