{"record":{"id":"a74442917df16d0d","repo":"Mintplex-Labs/anything-llm","slug":"invalid-folder-name-a74442","errorCode":null,"errorMessage":"Invalid folder name.","messagePattern":"Invalid folder name\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/utils/files/index.js","lineNumber":711,"sourceCode":" * Ensures a target folder exists under the documents storage path and moves\n * processed collector documents into it, updating each document's `location`\n * and `name` in-place. If the folder already exists, documents are merged\n * into it so repeated uploads to the same folder are idempotent.\n *\n * The folder must be a single path segment - see the note below on why.\n * @param {Array<{location: string, name: string}>} documents - documents returned by Collector.processDocument\n * @param {string} folderName - target folder name (e.g. \"my-notes\")\n * @param {string} basePath - base documents directory (overridable for testing)\n * @returns {string} the normalized folder name the documents were moved into\n * @throws {Error} if the folder name is empty, escapes basePath, or is nested\n */\nfunction moveProcessedDocsToFolder(\n  documents = [],\n  folderName = \"\",\n  basePath = documentsPath\n) {\n  const folder = normalizePath(folderName);\n  if (!folder) throw new Error(\"Invalid folder name.\");\n\n  // Deliberate: document storage is exactly two segments (`folder/file.json`)\n  // and docpath, the embedding pipeline and the vector cache all assume that\n  // shape. A nested folder name would produce documents that the file picker\n  // (which only enumerates one level below documentsPath) cannot see and that\n  // cannot be embedded. /v1/document/upload/:folderName historically accepted\n  // a URL-encoded separator here; that is now rejected.\n  if (folder.includes(\"/\") || folder.includes(\"\\\\\"))\n    throw new Error(\"Folder name cannot contain path separators.\");\n\n  const targetFolderPath = path.join(basePath, folder);\n  if (!isWithin(path.resolve(basePath), path.resolve(targetFolderPath)))\n    throw new Error(\"Invalid folder name.\");\n  if (!fs.existsSync(targetFolderPath))\n    fs.mkdirSync(targetFolderPath, { recursive: true });\n\n  for (const doc of documents) {\n    const currentFolder = path.dirname(doc.location);","sourceCodeStart":693,"sourceCodeEnd":729,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/server/utils/files/index.js#L693-L729","documentation":"Thrown by moveProcessedDocsToFolder() when normalizePath(folderName) returns an empty string. Because normalizePath already throws on \"..\"/\".\"/\"/\", reaching this line means the name consisted entirely of characters that path.normalize collapses to nothing (e.g. a single space, or only characters stripped upstream). It is the empty-folder-name guard for the document-storage layout that requires a real folder segment.","triggerScenarios":"POST to a document-upload endpoint whose :folderName is \"\", \" \", or whitespace-only; an automation pipeline that passes an undefined variable that stringifies to empty; a CLI tool that forgot to set the target folder argument.","commonSituations":"Replaying a collector run without a folder argument; a frontend form that allows submit on an empty folder field; a rename/move script iterating over a config map where one entry has no folder key.","solutions":["Require a non-empty folder name at the controller layer before calling moveProcessedDocsToFolder.","Trim and length-check the incoming folderName (e.g. reject if !folderName.trim()) and return 400.","If the folder is optional in your flow, default to a generated name (timestamp/uuid) before calling.","Add a unit test asserting empty and whitespace inputs are rejected upstream."],"exampleFix":"// before\nawait moveProcessedDocsToFolder(docs, folderName);\n\n// after\nconst name = (folderName || \"\").trim();\nif (!name) throw new UserError(\"folderName is required\", 400);\nawait moveProcessedDocsToFolder(docs, name);","handlingStrategy":"validation","validationCode":"const folder = (folderName || '').trim();\nif (!folder) throw new UserError('folderName is required', 400);","typeGuard":"function isNonEmptyFolderName(v): v is string {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  await moveProcessedDocsToFolder(docs, folderName);\n} catch (e) {\n  if (e.message === 'Invalid folder name.') return res.status(400).json({ error: e.message });\n  throw e;\n}","preventionTips":["Trim and length-check folder names at the API boundary.","Default to a generated slug when the folder is optional.","Frontend: disable submit while the folder field is empty."],"tags":["validation","filesystem","document-storage"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}