{"record":{"id":"60aa21497ed51ed9","repo":"Mintplex-Labs/anything-llm","slug":"file-not-found-filename","errorCode":null,"errorMessage":"File not found: ${filename}","messagePattern":"File not found: (.+?)","errorType":"http","errorClass":null,"httpStatus":404,"severity":"warning","filePath":"open-computer/services/interface-service/routes/deliverables.js","lineNumber":26,"sourceCode":"  safeFilename,\n  writeManifest,\n} = require(\"../utils/deliverables\");\n\nfunction registerDeliverableRoutes(app, { deliverablesDir }) {\n  app.get(\"/api/v1/deliverables\", (_req, res) => {\n    try {\n      res.json({ deliverables: readManifest(deliverablesDir) });\n    } catch {\n      res.json({ deliverables: [] });\n    }\n  });\n\n  app.get(\"/api/v1/deliverables/:filename\", (req, res) => {\n    const filename = safeFilename(req.params.filename);\n    const filepath = path.join(deliverablesDir, filename);\n\n    if (!fs.existsSync(filepath)) {\n      return res.status(404).json({ error: `File not found: ${filename}` });\n    }\n\n    const ext = filename.split(\".\").pop()?.toLowerCase();\n    const mismatch = fileExtensionMismatch(filepath, ext);\n    if (mismatch) {\n      return res.status(409).json({\n        error: `Refusing to download ${filename}: ${mismatch}.`,\n      });\n    }\n\n    res.setHeader(\"Content-Type\", MIME_TYPES[ext] || \"application/octet-stream\");\n    res.setHeader(\"Content-Disposition\", `attachment; filename=\"${filename}\"`);\n    fs.createReadStream(filepath).pipe(res);\n  });\n\n  app.delete(\"/api/v1/deliverables/:filename\", (req, res) => {\n    const filename = safeFilename(req.params.filename);\n    const filepath = path.join(deliverablesDir, filename);","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/3aec848f2885144aa8f1e53b9731a04310d5d558/open-computer/services/interface-service/routes/deliverables.js#L8-L44","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst res = await fetch(`${BASE}/api/v1/deliverables/${name}`);\n\n// after: resolve the exact name from the manifest first\nconst {deliverables} = await (await fetch(`${BASE}/api/v1/deliverables`)).json();\nconst hit = deliverables.find((d) => d.filename === name);\nif (!hit) throw new Error('deliverable no longer exists');\nconst res = await fetch(`${BASE}/api/v1/deliverables/${encodeURIComponent(hit.filename)}`);","handlingStrategy":"validation","validationCode":"const {deliverables} = await (await fetch(`${BASE}/api/v1/deliverables`)).json();\nconst exists = deliverables.some((d) => d.filename === wantedName);\nif (!exists) throw new Error(`'${wantedName}' is not in the manifest`);","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(`${BASE}/api/v1/deliverables/${encodeURIComponent(name)}`);\n  if (res.status === 404) return refreshManifest();\n  return await res.blob();\n} catch (e) { throw e; }","preventionTips":["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"],"tags":["http-404","file-download","deliverables","path-safety","interface-service"],"backgroundTag":"file-not-found","analyzedSha":"3aec848f2885144aa8f1e53b9731a04310d5d558","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}