{"record":{"id":"80f79cac5f165d08","repo":"Mintplex-Labs/anything-llm","slug":"errors-0-failed-to-embed-document","errorCode":null,"errorMessage":"errors[0] || \"Failed to embed document\"","messagePattern":"errors\\[0\\] \\|\\| \"Failed to embed document\"","errorType":"exception","errorClass":null,"httpStatus":500,"severity":"error","filePath":"server/models/workspaceParsedFiles.js","lineNumber":149,"sourceCode":"        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);\n      fs.unlinkSync(sourceFile);\n\n      const {\n        failedToEmbed = [],\n        errors = [],\n        embedded = [],\n      } = await Document.addDocuments(\n        workspace,\n        [`custom-documents/${path.basename(location)}`],\n        parsedFile.userId\n      );\n\n      if (failedToEmbed.length > 0)\n        throw new Error(errors[0] || \"Failed to embed document\");\n\n      const document = await Document.get({\n        workspaceId: workspace.id,\n        docpath: embedded[0],\n      });\n      return { success: true, error: null, document };\n    } catch (error) {\n      console.error(\"Failed to move and embed file:\", error);\n      return { success: false, error: error.message, document: null };\n    } finally {\n      await this.delete({\n        id: parseInt(fileId),\n        ...(user ? { userId: user.id } : {}),\n        workspaceId: workspace.id,\n      });\n    }\n  },\n","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/20f6d3546c1938bfea1ad304f58a592dddcc5948/server/models/workspaceParsedFiles.js#L131-L167","documentation":"Thrown when Document.addDocuments reports at least one path in failedToEmbed; the message is errors[0] (the first underlying embedder/vector error) or the generic fallback when errors is empty. By this point the file has already been copied into storage/documents/custom-documents and the source unlinked, and the finally block deletes the parsed-file row - so recovery must target the copied document, not a retry of this call. Caught internally and returned as { success: false, error, document: null }.","triggerScenarios":"Embedder unavailable or misconfigured (local embedding model not downloaded, remote embedder key invalid); vector store not writable (disk full, permissions); document text extraction fails on the format; embedding dimension mismatch with existing workspace vectors.","commonSituations":"Switching the embedder after a workspace already has vectors; storage permission changes after a container rebuild; oversized or scanned (textless) PDFs; upgrading with an incompatible vector index.","solutions":["Check the server log - the full cause is console.error'd as \"Failed to move and embed file\" and errors[0] is surfaced in the returned error","Verify the embedder works (System Settings -> AI Providers -> Embedder) by embedding a fresh small document","Ensure the storage directory is writable and has free space","Recover by embedding the already-copied file via Document.addDocuments(workspace, [\"custom-documents/<name>\"], userId), or re-upload the original"],"exampleFix":"// before\nconst { success, error } = await WorkspaceParsedFiles.moveToDocumentsAndEmbed(user, fileId, workspace);\nif (!success) throw new Error(error);\n\n// after - the file was already copied; re-embed that copy instead of retrying the parsed file\nconst { success, error } = await WorkspaceParsedFiles.moveToDocumentsAndEmbed(user, fileId, workspace);\nif (!success && /embed/i.test(error)) {\n  await Document.addDocuments(workspace, [`custom-documents/${fileName}`], parsedFile.userId);\n}","handlingStrategy":"retry","validationCode":"// Probe the embedder before batch-processing uploads\nconst { success } = await Document.addDocuments(workspace, [tinyProbeFile], systemUser);\nif (!success) {\n  return res.status(503).json({ error: \"Embedder unavailable - check AI provider settings\" });\n}","typeGuard":null,"tryCatchPattern":"const { success, error } = await WorkspaceParsedFiles.moveToDocumentsAndEmbed(user, fileId, workspace);\nif (!success && /embed/i.test(error)) {\n  // The file was already copied to storage/documents/custom-documents;\n  // retry embedding THAT copy - do not call moveToDocumentsAndEmbed again.\n  await withBackoff(() =>\n    Document.addDocuments(workspace, [`custom-documents/${fileName}`], parsedFile.userId)\n  );\n}","preventionTips":["Validate embedder configuration before running batch embed jobs","Keep vector storage on writable, persistent volumes with free space","Alert on the raw 'Failed to move and embed file' console output to catch root causes","Remember the parsed-file row is deleted in finally: never blindly retry the same fileId"],"tags":["embedding","documents","vector-store","workspace"],"backgroundTag":"document-embedding-failed","analyzedSha":"20f6d3546c1938bfea1ad304f58a592dddcc5948","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}