bmad-code-org/BMAD-METHOD · error · Error

${label} is not a directory: ${dirPath}

Error message

${label} is not a directory: ${dirPath}

What it means

Thrown by assertReadableDir when the path exists (stat succeeds) but stat.isDirectory() is false — a regular file or special file sits where a directory is required. Distinct from the not-exist and not-readable cases so the user knows the path is the wrong type.

Source

Thrown at tools/installer/core/install-paths.js:83

  }
  helpCatalog() {
    return path.join(this.configDir, 'bmad-help.csv');
  }
  moduleDir(name) {
    return path.join(this.bmadDir, name);
  }
  moduleConfig(name) {
    return path.join(this.bmadDir, name, 'config.yaml');
  }
}

async function assertReadableDir(dirPath, label) {
  const stat = await fs.stat(dirPath).catch(() => null);
  if (!stat) {
    throw new Error(`${label} does not exist: ${dirPath}`);
  }
  if (!stat.isDirectory()) {
    throw new Error(`${label} is not a directory: ${dirPath}`);
  }
  try {
    await fs.access(dirPath, fs.constants.R_OK);
  } catch {
    throw new Error(`${label} is not readable: ${dirPath}`);
  }
}

async function assertReadableFile(filePath, label) {
  const stat = await fs.stat(filePath).catch(() => null);
  if (!stat) {
    throw new Error(`${label} does not exist: ${filePath}`);
  }
  if (!stat.isFile()) {
    throw new Error(`${label} is not a file: ${filePath}`);
  }
  try {
    await fs.access(filePath, fs.constants.R_OK);

View on GitHub (pinned to b70486b9bd)

Solutions

  1. Inspect the path with `ls -la <dirPath>` to confirm what type of node occupies it.
  2. Remove or rename the offending file so the expected directory can be used.
  3. Re-extract/reinstall the package so directory structure is correct.
Defensive patterns

Strategy: validation

Validate before calling

const stat = await fs.stat(dirPath).catch(() => null);
if (stat && !stat.isDirectory()) {
  // surface a friendly error before the installer throws
}

Try / catch

try {
  await assertReadableDir(dirPath, label);
} catch (error) {
  if (error.message.includes('is not a directory')) { /* wrong type */ }
  throw error;
}

Prevention

When it happens

Trigger: InstallPaths.create() validates a directory path that is occupied by a file. E.g. srcDir resolves to a path where a file named like the expected directory exists.

Common situations: A file was accidentally created with the same name as an expected directory, a symlink points to a file instead of a directory, or a packaging step shipped a file where a directory was expected.

Related errors


AI-assisted analysis of bmad-code-org/BMAD-METHOD@b70486b9bd (2026-08-13). Data as JSON: /api/errors/60fae6319285acb1. Report an issue: GitHub.