Mintplex-Labs/anything-llm · error

Failed to download file

Error message

Failed to download file

What it means

Catch-all HTTP 500 from the generated-files download handler. Anything that throws after the early guards — setting headers (e.g. invalid characters in the sanitized display filename), an unexpected shape from getGeneratedFile (missing buffer), response.send failures, or client-abort edge cases — is logged as '[agentFileServer] Download error: <message>' server-side and returned to the client as this generic message. The console.error line is the only place the real cause appears.

Source

Thrown at server/endpoints/agentFileServer.js:85

        // Get mime type and set headers for download
        const mimeType = createFilesLib.getMimeType(`.${parsed.extension}`);
        const safeFilename = createFilesLib.sanitizeFilenameForHeader(
          fileSource.displayFilename || filename
        );
        response.setHeader("Content-Type", mimeType);
        response.setHeader(
          "Content-Disposition",
          `attachment; filename="${safeFilename}"`
        );
        response.setHeader("Content-Length", fileData.buffer.length);
        response.send(fileData.buffer);
        Telemetry.sendTelemetry("agent_generated_file_downloaded", {
          type: mimeType,
        }).catch(() => {});
        return;
      } catch (error) {
        console.error("[agentFileServer] Download error:", error.message);
        return response.status(500).json({ error: "Failed to download file" });
      }
    }
  );

  /**
   * Serve a generated image inline (so it can be used as an <img> src).
   * Validates that the requesting user has access to a chat that references
   * the image before serving it from storage/generated-images.
   */
  app.get(
    "/image-generation/generated-images/:filename",
    [validatedRequest, flexUserRoleValid([ROLES.all])],
    async (request, response) => {
      try {
        const fs = require("fs");
        const path = require("path");
        const {
          generatedImagesPath,

View on GitHub (pinned to 3aec848f28)

Solutions

  1. Correlate with the server console at the request timestamp — the '[agentFileServer] Download error:' line holds the actual error message
  2. Retry once; transient stream aborts and races often clear
  3. Manually verify the file exists in the storage directory and getGeneratedFile returns a buffer for that name
  4. If persistent, temporarily log the full error object (not just error.message) in the catch to get a stack, then fix the specific fault

Example fix

// before: only the message is logged, stacks are lost
console.error('[agentFileServer] Download error:', error.message);

// after: capture the stack while investigating
console.error('[agentFileServer] Download error:', error);
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const res = await fetch(url, {credentials: 'include'});
  if (res.status === 500) {
    // generic by design — the '[agentFileServer] Download error:' server log
    // at this timestamp holds the actual cause; retry once for transient aborts
    return await fetch(url, {credentials: 'include'});
  }
} catch (e) {
  // client/network-level failure
}

Prevention

When it happens

Trigger: fileData.buffer undefined because storage returned a record without content; Content-Disposition header containing newline/quote characters from a malformed displayFilename; socket closed by the client between the guards and response.send; ENOSPC or permission errors while streaming from the storage driver.

Common situations: Diagnosing production download failures where the HTTP message alone is useless; downloads that fail only for specific files (bad display names); transient failures under load that disappear on retry.

Related errors


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