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
- Pass the containing directory instead of the individual file, e.g. `wmill lint ./scripts`.
- Lint the whole project root (where wmill.yaml lives) and filter results rather than targeting one file.
- 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
- Remember `wmill lint` only accepts directories — never pass individual script files.
- Watch for shell glob expansion turning your argument into a single file path.
- Lint the project root and filter output instead of targeting single files.
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
- Directory not found: ${targetDirectory}
- Invalid migration name '${name}': use only letters, digits,
- File not found: ${filePath}
- Unknown workspace dependencies file format: ${path}. Valid f
- Cannot push flow ${remotePath}: step(s) reference non-worksp
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/41e30b541ab0b458.
Report an issue: GitHub.