{"record":{"id":"cd74bd6acdb4fc46","repo":"Mintplex-Labs/anything-llm","slug":"invalid-file-location","errorCode":null,"errorMessage":"Invalid file location.","messagePattern":"Invalid file location\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/utils/files/index.js","lineNumber":739,"sourceCode":"\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);\n    if (currentFolder === folder) continue;\n\n    const sourcePath = path.join(basePath, normalizePath(doc.location));\n    const destinationPath = path.join(\n      targetFolderPath,\n      path.basename(doc.location)\n    );\n\n    if (!isWithin(basePath, sourcePath) || !isWithin(basePath, destinationPath))\n      throw new Error(\"Invalid file location.\");\n\n    fs.renameSync(sourcePath, destinationPath);\n    doc.location = path.join(folder, path.basename(doc.location));\n    doc.name = path.basename(doc.location);\n  }\n\n  return folder;\n}\n\n/**\n * Purges the entire vector-cache folder and recreates it.\n * @returns {void}\n */\nfunction purgeEntireVectorCache() {\n  fs.rmSync(vectorCachePath, { recursive: true, force: true });\n  fs.mkdirSync(vectorCachePath);\n  return;\n}","sourceCodeStart":721,"sourceCodeEnd":757,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/server/utils/files/index.js#L721-L757","documentation":"Thrown inside moveProcessedDocsToFolder()'s per-document loop when either the computed sourcePath or destinationPath is not within basePath. Each document's location comes from the collector; if a doc.location is malformed (absolute, traversal-bearing, or already nested), the rename would move a file across the trust boundary, so the operation is aborted. This protects both reads (source) and writes (destination).","triggerScenarios":"A document in the `documents` array whose location is an absolute path, contains '..', or points outside documentsPath; a destination collision where path.basename produces a value that, when joined under the target folder, leaves basePath (rare, but possible with odd doc.location values).","commonSituations":"Stale or hand-edited document records whose location field was tampered with; a collector version that returned full paths instead of relative ones; concurrent uploads where one doc's location was rewritten mid-loop.","solutions":["Inspect the failing document's location field in the documents array and correct the record.","Ensure collector output uses relative, single-segment-prefixed locations (folder/file.json).","Run a data audit: SELECT docs whose location starts with '/' or contains '..' and repair them.","Wrap the call in try/catch at the endpoint and return 422 with the offending doc identifier for triage."],"exampleFix":"// before\nfor (const doc of documents) {\n  // ... builds sourcePath / destinationPath, throws if escapes\n}\n\n// after\nfor (const doc of documents) {\n  if (!doc.location || path.isAbsolute(doc.location) || doc.location.includes('..')) {\n    throw new UserError(`Refusing to move doc with unsafe location: ${doc.location}`, 422);\n  }\n  // ... safe to proceed\n}","handlingStrategy":"validation","validationCode":"for (const doc of documents) {\n  if (!doc.location || path.isAbsolute(doc.location) || doc.location.includes('..'))\n    throw new UserError(`Unsafe doc.location: ${doc.location}`, 422);\n}","typeGuard":"function isRelativeDocLocation(doc: any): doc is { location: string; name: string } {\n  return !!doc && typeof doc.location === 'string'\n    && !path.isAbsolute(doc.location) && !doc.location.includes('..');\n}","tryCatchPattern":"try {\n  await moveProcessedDocsToFolder(docs, folderName);\n} catch (e) {\n  if (e.message === 'Invalid file location.') return res.status(422).json({ error: e.message });\n  throw e;\n}","preventionTips":["Ensure collector output uses relative folder/file.json locations.","Audit stored document records for absolute or traversal locations.","Reject documents whose location is not within basePath before the move loop."],"tags":["path-traversal","security","filesystem","document-storage"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}