mastra-ai/mastra · error

Configured domain path "${directory}" is a file, expected a

Error message

Configured domain path "${directory}" is a file, expected a directory

What it means

After passing the traversal check, listDomainFiles() stats the resolved directory and throws if it exists but is a regular file instead of a directory. The storage expects each domain path to be a directory of JSON files.

Source

Thrown at packages/core/src/storage/filesystem-db.ts:111

    renameSync(tmpPath, filePath);
  }

  /**
   * Clear all data from a domain JSON file.
   */
  clearDomain(filename: string): void {
    this.writeDomain(filename, {});
  }

  listDomainFiles(directory: string, extension = '.json'): string[] {
    const baseDir = resolve(this.dir, directory);
    const rootDir = resolve(this.dir);
    if (!baseDir.startsWith(rootDir + sep) && baseDir !== rootDir) {
      throw new Error(`Path traversal detected: directory "${directory}" escapes storage directory`);
    }
    if (!existsSync(baseDir)) return [];
    if (!statSync(baseDir).isDirectory()) {
      throw new Error(`Configured domain path "${directory}" is a file, expected a directory`);
    }

    return readdirSync(baseDir)
      .filter(file => extname(file) === extension && statSync(join(baseDir, file)).isFile())
      .map(file => `${directory}/${file}`);
  }

  /**
   * Check whether a domain file currently exists on disk.
   */
  domainFileExists(filename: string): boolean {
    const filePath = resolve(this.dir, filename);
    const rootDir = resolve(this.dir);
    if (!filePath.startsWith(rootDir + sep) && filePath !== rootDir) {
      throw new Error(`Path traversal detected: file "${filename}" escapes storage directory`);
    }
    return existsSync(filePath);
  }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Remove or rename the file at that path so the domain path can be a directory, or move its contents into a directory of that name.
  2. Fix the `directory` argument to point at an actual directory within storage.
  3. Inspect the storage root (`this.dir`) to see what occupies the path: `ls -la <root>/<directory>`.
  4. If migrating layouts, move legacy single-file data into the per-domain directory structure.

Example fix

// before
fs.writeFileSync(path.join(dir, 'workflows'), data); // file where dir expected

// after
fs.mkdirSync(path.join(dir, 'workflows'), { recursive: true });
fs.writeFileSync(path.join(dir, 'workflows', 'entry.json'), data);
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
function ensureDomainDir(base, dir) {
  const p = require('path').join(base, dir);
  if (fs.existsSync(p) && !fs.statSync(p).isDirectory()) {
    throw new Error(`${p} is a file; expected a directory`);
  }
}

Try / catch

try {
  return db.listDomainFiles(dir);
} catch (e) {
  if (e.message.includes('is a file, expected a directory')) {
    // surface a clear config/migration error to the operator
    throw new Error(`Storage layout invalid at "${dir}": move or remove the file.`);
  }
  throw e;
}

Prevention

When it happens

Trigger: The configured domain path (e.g. `directory` argument or a storage dir layout) points at an existing file, so `readdirSync` would fail; listDomainFiles is called on a path where a file was placed where a directory is expected.

Common situations: A file (e.g. an accidental archive, editor artifact, or JSON written to the directory path) collides with a domain directory name; migrating storage layouts where old data was a single file; wrong `directory` argument naming a file.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/eb3e3d817cd0b330. Report an issue: GitHub.