Mintplex-Labs/anything-llm · warning
File not found: ${filename}
Error message
File not found: ${filename} What it means
Returned (HTTP 404) by GET /api/v1/deliverables/:filename when path.join(deliverablesDir, safeFilename(req.params.filename)) does not exist on disk. safeFilename (from utils/deliverables) strips traversal and unsafe characters, so a mangled or renamed URL can sanitize to a different lookup key and miss. The manifest served by GET /api/v1/deliverables is the source of truth for which names exist.
Source
Thrown at open-computer/services/interface-service/routes/deliverables.js:26
safeFilename,
writeManifest,
} = require("../utils/deliverables");
function registerDeliverableRoutes(app, { deliverablesDir }) {
app.get("/api/v1/deliverables", (_req, res) => {
try {
res.json({ deliverables: readManifest(deliverablesDir) });
} catch {
res.json({ deliverables: [] });
}
});
app.get("/api/v1/deliverables/:filename", (req, res) => {
const filename = safeFilename(req.params.filename);
const filepath = path.join(deliverablesDir, filename);
if (!fs.existsSync(filepath)) {
return res.status(404).json({ error: `File not found: ${filename}` });
}
const ext = filename.split(".").pop()?.toLowerCase();
const mismatch = fileExtensionMismatch(filepath, ext);
if (mismatch) {
return res.status(409).json({
error: `Refusing to download ${filename}: ${mismatch}.`,
});
}
res.setHeader("Content-Type", MIME_TYPES[ext] || "application/octet-stream");
res.setHeader("Content-Disposition", `attachment; filename="${filename}"`);
fs.createReadStream(filepath).pipe(res);
});
app.delete("/api/v1/deliverables/:filename", (req, res) => {
const filename = safeFilename(req.params.filename);
const filepath = path.join(deliverablesDir, filename);View on GitHub (pinned to 3aec848f28)
Solutions
- GET /api/v1/deliverables first and use an exact filename from the manifest, URL-encoded verbatim
- Confirm the file still exists — the DELETE /api/v1/deliverables/:filename route removes both manifest entry and file
- Verify the service's configured deliverablesDir matches the directory the agent writes deliverables into
- If the agent is mid-write, wait for it to finish and refresh the manifest before downloading
Example fix
// before
const res = await fetch(`${BASE}/api/v1/deliverables/${name}`);
// after: resolve the exact name from the manifest first
const {deliverables} = await (await fetch(`${BASE}/api/v1/deliverables`)).json();
const hit = deliverables.find((d) => d.filename === name);
if (!hit) throw new Error('deliverable no longer exists');
const res = await fetch(`${BASE}/api/v1/deliverables/${encodeURIComponent(hit.filename)}`); Defensive patterns
Strategy: validation
Validate before calling
const {deliverables} = await (await fetch(`${BASE}/api/v1/deliverables`)).json();
const exists = deliverables.some((d) => d.filename === wantedName);
if (!exists) throw new Error(`'${wantedName}' is not in the manifest`); Try / catch
try {
const res = await fetch(`${BASE}/api/v1/deliverables/${encodeURIComponent(name)}`);
if (res.status === 404) return refreshManifest();
return await res.blob();
} catch (e) { throw e; } Prevention
- Always resolve filenames through GET /api/v1/deliverables instead of constructing them by hand
- URL-encode the manifest filename verbatim (encodeURIComponent) in download URLs
- Refresh the manifest after the agent finishes a run and after any DELETE
When it happens
Trigger: GET /api/v1/deliverables/report.pdf after the agent DELETEd or overwrote the file; downloading before the agent finished writing it; a filename whose URL-decoded form contains characters safeFilename strips (../, slashes, exotic unicode), changing the name used for the existsSync check; deliverablesDir pointing at a different folder than the one the agent writes to.
Common situations: Stale UI manifest listing a deliverable that was since deleted; environment config differences (deliverablesDir env var) between the generating and downloading environments; hand-typed or truncated URLs; double-encoding issues in proxies.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- no pending help request with that id
- File not found or access denied
- File not found in storage
- Failed to download file
- agent not running
AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18).
Data as JSON: /api/errors/60aa21497ed51ed9.
Report an issue: GitHub.