danny-avila/LibreChat · error

Invalid file path: ${filepath}

Error message

Invalid file path: ${filepath}

What it means

Thrown by getLocalFileStream when the filepath includes '/uploads/' but the portion after it is empty — meaning the filepath is exactly '/uploads/' or ends with '/uploads/'. The split produces an empty basePath, indicating no actual file was specified within the uploads directory.

Source

Thrown at api/server/services/Files/Local/crud.js:335

  return { filepath, bytes, height, width };
}

/**
 * Retrieves a readable stream for a file from local storage.
 *
 * @param {ServerRequest} req - The request object from Express
 * @param {string} filepath - The filepath.
 * @returns {ReadableStream} A readable stream of the file.
 */
async function getLocalFileStream(req, filepath) {
  try {
    const appConfig = req.config;
    if (filepath.includes('/uploads/')) {
      const basePath = filepath.split('/uploads/')[1];

      if (!basePath) {
        logger.warn(`Invalid base path: ${filepath}`);
        throw new Error(`Invalid file path: ${filepath}`);
      }

      const fullPath = path.join(appConfig.paths.uploads, basePath);
      const uploadsDir = appConfig.paths.uploads;

      const rel = path.relative(uploadsDir, fullPath);
      if (rel.startsWith('..') || path.isAbsolute(rel) || rel.includes(`..${path.sep}`)) {
        logger.warn(`Invalid relative file path: ${filepath}`);
        throw new Error(`Invalid file path: ${filepath}`);
      }

      return fs.createReadStream(fullPath);
    } else if (filepath.includes('/images/')) {
      const basePath = filepath.split('/images/')[1];

      if (!basePath) {
        logger.warn(`Invalid base path: ${filepath}`);
        throw new Error(`Invalid file path: ${filepath}`);

View on GitHub (pinned to 5ff282f900)

Solutions

  1. Verify the filepath passed to getLocalFileStream is a complete path like /uploads/{userId}/{file_id}__{filename}.
  2. Validate filepath format before calling getLocalFileStream: it must contain a non-empty segment after /uploads/.
  3. Audit the caller to ensure filepath is sourced from a validated database record, not from client input.
  4. Return a 400 Bad Request at the route level if the filepath is incomplete.

Example fix

// before
const stream = await getLocalFileStream(req, filepath);

// after — validate before calling
if (!filepath || filepath.endsWith('/uploads/') || filepath.endsWith('/images/')) {
  throw new Error('Incomplete file path: missing filename');
}
const stream = await getLocalFileStream(req, filepath);
Defensive patterns

Strategy: validation

Validate before calling

if (filepath.includes('/uploads/')) {
  const basePath = filepath.split('/uploads/')[1];
  if (!basePath) {
    throw new Error('Incomplete uploads path: missing filename');
  }
}

Type guard

function hasUploadFilename(filepath: string): boolean {
  if (!filepath.includes('/uploads/')) return true;
  const basePath = filepath.split('/uploads/')[1];
  return basePath != null && basePath.length > 0;
}

Try / catch

try {
  const stream = await getLocalFileStream(req, filepath);
} catch (error) {
  if (error.message.startsWith('Invalid file path')) {
    return res.status(400).json({ error: 'Incomplete file path' });
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling getLocalFileStream(req, filepath) where filepath is '/uploads/' or '/some/prefix/uploads/' with nothing following the final '/uploads/' segment. The basePath extracted via split('/uploads/')[1] is undefined or empty.

Common situations: A caller constructs a filepath by concatenating '/uploads/' with a missing or empty filename. Or a database record stores a bare '/uploads/' path. Or a URL routing bug passes the uploads prefix without the user-specific subpath.

Related errors


AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12). Data as JSON: /api/errors/8e086331aa62ae9a. Report an issue: GitHub.