{"record":{"id":"a34c25cb27153c80","repo":"Mintplex-Labs/anything-llm","slug":"failed-to-serve-image","errorCode":null,"errorMessage":"Failed to serve image","messagePattern":"Failed to serve image","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"server/endpoints/agentFileServer.js","lineNumber":135,"sourceCode":"          return response\n            .status(404)\n            .json({ error: \"Image not found or access denied\" });\n\n        const imagePath = path.resolve(generatedImagesPath, filename);\n        let imageBuffer;\n        try {\n          imageBuffer = await fs.promises.readFile(imagePath);\n        } catch {\n          return response\n            .status(404)\n            .json({ error: \"Image not found in storage\" });\n        }\n\n        response.setHeader(\"Content-Type\", \"image/png\");\n        return response.send(imageBuffer);\n      } catch (error) {\n        console.error(\"[agentFileServer] Image serve error:\", error.message);\n        return response.status(500).json({ error: \"Failed to serve image\" });\n      }\n    }\n  );\n}\n\n/**\n * Locates the source record (a workspace chat or a scheduled job run) that\n * references the given storage filename, and confirms the requester has access.\n *\n * Search order:\n *   1. Workspace chats the user can access (per multi-user permissions).\n *   2. Scheduled job runs — single-user only, so no per-user access check.\n *\n * @param {string} storageFilename\n * @param {{ user: object|null, isMultiUser: boolean }} ctx\n * @returns {Promise<{workspaceId: number|null, displayFilename: string}|null>}\n */\nasync function findFileSource(storageFilename, { user, isMultiUser }) {","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/3aec848f2885144aa8f1e53b9731a04310d5d558/server/endpoints/agentFileServer.js#L117-L153","documentation":"Catch-all HTTP 500 from the generated-image serve handler. Any throw outside the inner readFile guard — userFromSession failures that slip through, an exception from findFileSource's database query, response.send errors, header issues — is logged server-side as '[agentFileServer] Image serve error: <message>' and returned to the client as this generic message. The real cause only exists in the server console.","triggerScenarios":"A database error inside findFileSource (the workspace-chat lookup) while authorizing the image; response.send failing after a client abort; an unexpected throw from userFromSession for a malformed session cookie; fs errors other than ENOENT surfacing from the surrounding logic.","commonSituations":"Broken <img> tags in production chats with no client-side detail; intermittent failures tied to DB load; post-upgrade schema mismatches in the chat tables used by findFileSource.","solutions":["Check the server console for '[agentFileServer] Image serve error:' at the request time — it carries the underlying message","Reload/retry once; aborted-connection races and transient DB errors often clear","If every image fails, test the DB queries behind findFileSource directly — a systemic 500 points at the authorization lookup, not the files","Log the full error object temporarily to obtain a stack for the specific fault"],"exampleFix":"// before: message-only logging loses stacks\nconsole.error('[agentFileServer] Image serve error:', error.message);\n\n// after: full error while debugging\nconsole.error('[agentFileServer] Image serve error:', error);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(imgUrl, {credentials: 'include'});\n  if (res.status === 500) {\n    // generic by design — check the '[agentFileServer] Image serve error:' server log\n    // for the real cause; a single retry covers aborted-connection races\n    return await fetch(imgUrl, {credentials: 'include'});\n  }\n} catch (e) {\n  // network-level failure reaching the server\n}","preventionTips":["Pair every report of this 500 with the server-side console line at the same timestamp","If all images 500 at once, suspect the DB behind findFileSource rather than individual files","Use onerror handlers on <img> tags to swap in a placeholder instead of surfacing broken images"],"tags":["http-500","image-generation","generic-catch","diagnostics"],"backgroundTag":"internal-server-error","analyzedSha":"3aec848f2885144aa8f1e53b9731a04310d5d558","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}