{"record":{"id":"c8a7bca34a23923e","repo":"Mintplex-Labs/anything-llm","slug":"file-not-found","errorCode":null,"errorMessage":"File not found","messagePattern":"File not found","errorType":"exception","errorClass":null,"httpStatus":500,"severity":"error","filePath":"server/models/workspaceParsedFiles.js","lineNumber":117,"sourceCode":"    });\n    return _sum.tokenCountEstimate || 0;\n  },\n\n  /**\n   * Moves a parsed file to the documents and embeds it.\n   * @param {import(\"@prisma/client\").users | null} user - The user performing the operation.\n   * @param {number} fileId - The ID of the parsed file.\n   * @param {import(\"@prisma/client\").workspaces} workspace - The workspace the file belongs to.\n   * @returns {Promise<{ success: boolean, error: string | null, document: import(\"@prisma/client\").workspace_documents | null }>} The result of the operation.\n   */\n  moveToDocumentsAndEmbed: async function (user = null, fileId, workspace) {\n    try {\n      const parsedFile = await this.get({\n        id: parseInt(fileId),\n        ...(user ? { userId: user.id } : {}),\n        workspaceId: workspace.id,\n      });\n      if (!parsedFile) throw new Error(\"File not found\");\n\n      // Get file location from metadata\n      const metadata = safeJsonParse(parsedFile.metadata, {});\n      const location = metadata.location;\n      if (!location) throw new Error(\"No file location in metadata\");\n\n      // Get file from metadata location\n      const sourceFile = path.join(directUploadsPath, path.basename(location));\n      if (!fs.existsSync(sourceFile)) throw new Error(\"Source file not found\");\n\n      // Move to custom-documents\n      const customDocsPath = path.join(documentsPath, \"custom-documents\");\n      if (!fs.existsSync(customDocsPath))\n        fs.mkdirSync(customDocsPath, { recursive: true });\n\n      // Copy the file to custom-documents\n      const targetPath = path.join(customDocsPath, path.basename(location));\n      fs.copyFileSync(sourceFile, targetPath);","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/20f6d3546c1938bfea1ad304f58a592dddcc5948/server/models/workspaceParsedFiles.js#L99-L135","documentation":"Thrown by WorkspaceParsedFiles.moveToDocumentsAndEmbed when no parsed-file row matches the given id (plus the optional userId filter and workspaceId). The method is one-shot: its finally block deletes the parsed-file row whether embedding succeeds or fails, so a second call with the same fileId always lands here. The throw is caught internally and returned to callers as { success: false, error: \"File not found\", document: null }, not propagated.","triggerScenarios":"Calling moveToDocumentsAndEmbed twice for the same fileId (the first attempt's finally already deleted the row); passing a non-admin user whose id does not match the row's userId; using a fileId from a different workspace; a queued job and a manual API call racing on the same file.","commonSituations":"Retry logic that resubmits after a failed embed; double-clicked \"move to documents\" actions; background workers and user-triggered requests processing the same upload; passing admin (user=null) vs uploader contexts inconsistently.","solutions":["Pre-check WorkspaceParsedFiles.get({ id, workspaceId, ...(user ? { userId: user.id } : {}) }) returns a row before calling","Never re-invoke with the same fileId after any attempt - the row is deleted in finally","Re-upload the source file to create a fresh parsed-file record if the row is gone","Pass the correct user context: admin/system paths use user=null to skip the userId filter"],"exampleFix":"// before\nconst result = await WorkspaceParsedFiles.moveToDocumentsAndEmbed(user, fileId, workspace);\n\n// after\nconst parsed = await WorkspaceParsedFiles.get({\n  id: Number(fileId),\n  workspaceId: workspace.id,\n  ...(user ? { userId: user.id } : {}),\n});\nif (!parsed) return res.status(404).json({ error: \"File not found\" });\nconst result = await WorkspaceParsedFiles.moveToDocumentsAndEmbed(user, fileId, workspace);","handlingStrategy":"validation","validationCode":"const parsed = await WorkspaceParsedFiles.get({\n  id: Number(fileId),\n  workspaceId: workspace.id,\n  ...(user ? { userId: user.id } : {}),\n});\nif (!parsed) return res.status(404).json({ error: \"File not found\" });\nconst result = await WorkspaceParsedFiles.moveToDocumentsAndEmbed(user, fileId, workspace);","typeGuard":null,"tryCatchPattern":"// The method does not throw; it returns a result object\nconst { success, error, document } = await WorkspaceParsedFiles.moveToDocumentsAndEmbed(user, fileId, workspace);\nif (!success) return res.status(404).json({ error });","preventionTips":["Treat the call as one-shot: the parsed-file row is deleted in finally, successful or not","Disable the UI action while a job is pending to prevent double submission","Verify id + userId + workspaceId match before scheduling the job"],"tags":["file","not-found","workspace","database"],"backgroundTag":"record-not-found","analyzedSha":"20f6d3546c1938bfea1ad304f58a592dddcc5948","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}