{"record":{"id":"c74f81c94e01eae5","repo":"Mintplex-Labs/anything-llm","slug":"filename-is-required","errorCode":null,"errorMessage":"Filename is required","messagePattern":"Filename is required","errorType":"http","errorClass":null,"httpStatus":400,"severity":"info","filePath":"server/endpoints/agentFileServer.js","lineNumber":37,"sourceCode":" * and ownership validation.\n */\nfunction agentFileServerEndpoints(app) {\n  if (!app) return;\n\n  /**\n   * Download a generated file by its storage filename.\n   * Validates that the requesting user has access to the workspace\n   * where the file was generated.\n   */\n  app.get(\n    \"/agent-skills/generated-files/:filename\",\n    [validatedRequest, flexUserRoleValid([ROLES.all])],\n    async (request, response) => {\n      try {\n        const user = await userFromSession(request, response);\n        const { filename } = request.params;\n        if (!filename)\n          return response.status(400).json({ error: \"Filename is required\" });\n\n        // Validate filename format\n        const parsed = createFilesLib.parseFilename(filename);\n        if (!parsed) {\n          return response\n            .status(400)\n            .json({ error: \"Invalid filename format\" });\n        }\n\n        // Find a chat or scheduled job run that references this file\n        const fileSource = await findFileSource(filename, {\n          user,\n          isMultiUser: multiUserMode(response),\n        });\n\n        if (!fileSource) {\n          return response.status(404).json({\n            error: \"File not found or access denied\",","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/3aec848f2885144aa8f1e53b9731a04310d5d558/server/endpoints/agentFileServer.js#L19-L55","documentation":"Returned (HTTP 400) by GET /agent-skills/generated-files/:filename when the filename param is falsy. In practice this is nearly unreachable through Express itself — the :filename route segment cannot match an empty path — so hitting it means the request reached the handler without a real segment: a proxy rewrite that strips it, or programmatic invocation of the route with an empty string.","triggerScenarios":"A reverse-proxy rewrite rule that forwards /agent-skills/generated-files/ with the trailing segment stripped; client URL concatenation bugs that drop the filename (usually caught earlier by the router as a plain 404); direct handler tests passing '' as the param.","commonSituations":"nginx/traefik rewrite misconfigurations; hand-built URL strings with a trailing slash and empty variable interpolation; monitoring probes hitting the bare collection path.","solutions":["Request /agent-skills/generated-files/<fileType>-<uuid>.<ext> with a real storage filename taken from the chat artifact link","Fix proxy rewrite rules so the :filename segment survives forwarding","Log the full incoming URL server-side to see what actually arrived when this fires"],"exampleFix":"# before: proxy strips the segment\nlocation /agent-skills/generated-files/ { proxy_pass http://app/agent-skills/generated-files/; }\n\n# after: preserve the full path\nlocation /agent-skills/generated-files/ { proxy_pass http://app; }","handlingStrategy":"validation","validationCode":"function downloadUrl(filename) {\n  if (!filename) throw new Error('storage filename required');\n  return `/agent-skills/generated-files/${encodeURIComponent(filename)}`;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never issue the request without a concrete filename variable in hand","Test proxy rewrites with a known-good filename before wiring the UI","Log the arriving full URL server-side if this ever fires — something upstream stripped the segment"],"tags":["http-400","required-parameter","file-download","defensive-guard"],"backgroundTag":"missing-required-argument","analyzedSha":"3aec848f2885144aa8f1e53b9731a04310d5d558","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}