{"record":{"id":"4fb2d907b78b6874","repo":"mastra-ai/mastra","slug":"filesystemstorage-path-must-be-a-non-empty-relat","errorCode":null,"errorMessage":"[FilesystemStorage] path must be a non-empty relative path.","messagePattern":"\\[FilesystemStorage\\] path must be a non-empty relative path\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/storage/domains/filesystem/base.ts","lineNumber":53,"sourceCode":"interface FilesystemSnapshotDbRow extends Record<string, unknown> {\n  id: string;\n  resource_id: string;\n  thread_id: string;\n  files: FilesystemFile[];\n  captured_at: Date;\n}\n\nfunction assertIdentifier(value: string, label: string): void {\n  if (!value.trim()) throw new Error(`[FilesystemStorage] ${label} must not be empty.`);\n}\n\nfunction assertRelativePath(value: string): void {\n  if (\n    !value ||\n    value.startsWith('/') ||\n    value.split('/').some(segment => !segment || segment === '.' || segment === '..')\n  ) {\n    throw new Error('[FilesystemStorage] path must be a non-empty relative path.');\n  }\n}\n\nfunction assertScope(args: { resourceId: string; threadId: string }): void {\n  assertIdentifier(args.resourceId, 'resourceId');\n  assertIdentifier(args.threadId, 'threadId');\n}\n\nfunction validateFiles(files: FilesystemFile[]): void {\n  const paths = new Set<string>();\n\n  for (const file of files) {\n    assertRelativePath(file.path);\n    if (paths.has(file.path)) throw new Error(`[FilesystemStorage] duplicate file path: ${file.path}`);\n    paths.add(file.path);\n  }\n}\n","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/storage/domains/filesystem/base.ts#L35-L71","documentation":"assertRelativePath enforces that file paths stored in FilesystemStorage are non-empty, relative, and composed only of safe segments — no leading '/', no empty, '.', or '..' segments. This prevents path traversal and absolute-path writes. Violating any of these throws this error via validateFiles.","triggerScenarios":"Calling a file-writing method (e.g. via replaceFiles → validateFiles) with a FilesystemFile whose path is '', starts with '/', or contains segments like '..', './', or double slashes.","commonSituations":"Joining an absolute filesystem path directly instead of a storage-relative path; user-supplied filenames containing '..'; path.normalize output retaining a leading slash; string concatenation producing '//'.","solutions":["Strip the storage root prefix so paths are relative","Sanitize/reject segments equal to '.', '..' or empty before calling the API","Normalize user-provided filenames (remove traversal, collapse slashes)","Use a path-join helper that always yields relative, clean segments"],"exampleFix":"// before\nawait storage.replaceFiles({ resourceId, threadId, files: [{ path: `/uploads/${userFile}`, ... }] });\n// after\nconst safe = userFile.replaceAll('..', '').replace(/^\\/+/, '');\nawait storage.replaceFiles({ resourceId, threadId, files: [{ path: `uploads/${safe}`, ... }] });","handlingStrategy":"validation","validationCode":"function isSafeRelativePath(p: string): boolean {\n  return !!p && !p.startsWith('/') && p.split('/').every(s => !!s && s !== '.' && s !== '..');\n}\nif (!isSafeRelativePath(file.path)) throw new Error(`Unsafe path: ${file.path}`);","typeGuard":"function isFilesystemFile(f: unknown): f is FilesystemFile {\n  return typeof f === 'object' && f !== null &&\n    typeof (f as FilesystemFile).path === 'string' && isSafeRelativePath((f as FilesystemFile).path);\n}","tryCatchPattern":"try {\n  await storage.replaceFiles({ resourceId, threadId, files });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('path must be a non-empty relative path')) {\n    throw new BadRequest(`Invalid file path in batch: ${e.message}`);\n  }\n  throw e;\n}","preventionTips":["Always store paths relative to the storage root","Sanitize user-supplied filenames (strip '..' and leading slashes)","Write a shared sanitizePath helper and use it for every write","Add unit tests for traversal attempts like '../../etc/passwd'"],"tags":["validation","path","filesystem","path-traversal"],"backgroundTag":"invalid-path","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}