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

  1. GET /api/v1/deliverables first and use an exact filename from the manifest, URL-encoded verbatim
  2. Confirm the file still exists — the DELETE /api/v1/deliverables/:filename route removes both manifest entry and file
  3. Verify the service's configured deliverablesDir matches the directory the agent writes deliverables into
  4. 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

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


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/60aa21497ed51ed9. Report an issue: GitHub.