mastra-ai/mastra · error

Directory already exists and is not empty: ${targetDir}

Error message

Directory already exists and is not empty: ${targetDir}

What it means

scaffoldPlugin refuses to generate a new plugin into an existing, non-empty directory. Because scaffolding writes template files unconditionally, an occupied target directory would be overwritten or mixed with stale content; the guard prevents accidental data loss. The resolved target is projectRoot (default cwd) joined with the given targetDir.

Source

Thrown at mastracode/sdk/src/plugins/scaffold.ts:35

  options: Pick<ScaffoldPluginOptions, 'projectRoot' | 'configDir'> = {},
): string {
  if (isBarePluginName(target)) {
    return path.join(
      options.projectRoot ?? process.cwd(),
      options.configDir ?? DEFAULT_CONFIG_DIR,
      'plugins',
      'sources',
      'local',
      target,
    );
  }
  return path.resolve(options.projectRoot ?? process.cwd(), target);
}

export function scaffoldPlugin(targetDir: string, options: ScaffoldPluginOptions = {}): string {
  const dir = resolveScaffoldTarget(targetDir, options);
  if (fs.existsSync(dir) && fs.readdirSync(dir).length > 0) {
    throw new Error(`Directory already exists and is not empty: ${targetDir}`);
  }

  const packageName =
    path
      .basename(dir)
      .toLowerCase()
      .replace(/[^a-z0-9_.-]+/g, '-')
      .replace(/^-|-$/g, '') || 'mastracode-plugin';
  const pluginId = options.id ?? packageName;
  const pluginName = options.name ?? humanizeName(packageName);

  fs.mkdirSync(path.join(dir, 'src'), { recursive: true });
  fs.writeFileSync(
    path.join(dir, 'package.json'),
    `${JSON.stringify(
      {
        name: packageName,
        type: 'module',

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Choose a new, unused target directory name and re-run the scaffold command.
  2. If the directory is leftover from a failed scaffold, delete it (verify contents first) and re-run.
  3. If you intended to scaffold there, move the existing files aside, scaffold, then restore what you need.
  4. Pass an explicit projectRoot option if the target resolved relative to the wrong cwd.

Example fix

// before
$ mastracode plugin create my-plugin
// Error: Directory already exists and is not empty: my-plugin
// after — remove leftovers or use a fresh dir
$ rm -rf my-plugin && mastracode plugin create my-plugin
// or
$ mastracode plugin create my-plugin-v2
Defensive patterns

Strategy: validation

Validate before calling

const target = path.resolve(projectRoot, targetDir);
if (fs.existsSync(target) && fs.readdirSync(target).length > 0) {
  throw new Error(`Choose a different scaffold target; ${targetDir} is not empty`);
}

Try / catch

try {
  scaffoldPlugin(targetDir, { projectRoot });
} catch (err) {
  if (err instanceof Error && err.message.includes('already exists and is not empty')) {
    console.error(`Target occupied: ${err.message}. Pick a new name or clear the directory.`);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling scaffoldPlugin(targetDir) or `mastracode create plugin <dir>` (prepare/createdDir flow) where resolveScaffoldTarget resolves to a path that already exists and fs.readdirSync shows at least one file, including hidden ones like .git or .DS_Store.

Common situations: Re-running a scaffold command after a partial/failed first attempt left files behind; scaffolding into a directory that already holds a real plugin; accidentally passing "." or the project root as targetDir, which always contains files.

Related errors


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