windmill-labs/windmill · error · Error

Path is not a directory: ${targetDirectory}

Error message

Path is not a directory: ${targetDirectory}

What it means

Thrown by `wmill lint` (runLint) when the target path exists but is a file (or other non-directory node) rather than a directory. The lint command walks a directory of scripts/flows/apps, so a single-file target is rejected with this explicit message.

Source

Thrown at cli/src/commands/lint/lint.ts:664

export async function runLint(
  opts: LintOptions,
  directory?: string,
): Promise<LintReport> {
  const initialCwd = process.cwd();
  const explicitTargetDirectory = directory
    ? path.resolve(initialCwd, directory)
    : undefined;

  const { json: _json, ...syncOpts } = opts;
  const mergedOpts = await mergeConfigWithConfigFile(syncOpts);
  const targetDirectory = explicitTargetDirectory ?? process.cwd();

  const stats = await stat(targetDirectory).catch(() => null);
  if (!stats) {
    throw new Error(`Directory not found: ${targetDirectory}`);
  }
  if (!stats.isDirectory()) {
    throw new Error(`Path is not a directory: ${targetDirectory}`);
  }

  // When the user specifies a subdirectory (that doesn't contain wmill.yaml),
  // skip include/exclude filters since they're relative to the project root.
  const isSubdirectory = explicitTargetDirectory &&
    !(await stat(path.join(targetDirectory, "wmill.yaml")).catch(() => null));
  const ignore = isSubdirectory
    ? (_p: string, _isDir: boolean) => false
    : await ignoreF(mergedOpts);
  const root = await FSFSElement(targetDirectory, [], false);
  const validator = new WindmillYamlValidator();

  const warnings: LintWarning[] = [];
  const issues: FileIssue[] = [];
  let scannedFiles = 0;
  let validatedFiles = 0;
  let validFiles = 0;
  let skippedUnsupportedFiles = 0;

View on GitHub (pinned to e474e8803c)

Solutions

  1. Pass the containing directory instead of the individual file, e.g. `wmill lint ./scripts`.
  2. Lint the whole project root (where wmill.yaml lives) and filter results rather than targeting one file.
  3. If you intended to lint a file, check whether the CLI version you run supports a file target; otherwise upgrade or use the directory scope.

Example fix

// before
wmill lint ./scripts/cleanup.ts

// after
wmill lint ./scripts
Defensive patterns

Strategy: validation

Validate before calling

const st = fs.statSync(target);
if (!st.isDirectory()) throw new Error(`${target} is a file; pass its parent directory instead`);

Try / catch

try {
  await runLint(opts, dir);
} catch (e: any) {
  if (e.message.startsWith("Path is not a directory")) {
    console.error(`${e.message} — pass the containing directory, e.g. \`wmill lint ./scripts\``);
  }
  process.exitCode = 2;
}

Prevention

When it happens

Trigger: Running `wmill lint path/to/script.ts` (a file) instead of the containing directory, or passing a glob that expanded to a file.

Common situations: Wanting to lint a single script but the CLI only supports directory targets; shell tab-completion picked a file; passing a config file (wmill.yaml) as the target by mistake.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/41e30b541ab0b458. Report an issue: GitHub.