windmill-labs/windmill · error
Path is not a directory
Error message
Path is not a directory
What it means
The CLI's config-directory resolver (`throwIfNotDirectory`, called from `ensureDir`) stats a candidate configuration path and throws if the path exists but is a file (or symlink to a file) rather than a directory. This guards directory creation/setup of the Windmill config location (e.g. `~/.config/windmill`). It means the expected config directory path is occupied by something that is not a directory.
Source
Thrown at cli/windmill-utils-internal/src/config/config.ts:25
export const WINDMILL_ACTIVE_INSTANCE_FILE = "activeInstance";
function getEnv(key: string): string | undefined {
return process.env[key];
}
function getOS(): "linux" | "darwin" | "windows" | null {
const platform = process.platform;
switch (platform) {
case "linux": return "linux";
case "darwin": return "darwin";
case "win32": return "windows";
default: return null;
}
}
function throwIfNotDirectory(fileInfo: import("node:fs").Stats): void {
if (!fileInfo.isDirectory()) {
throw new Error("Path is not a directory");
}
}
function config_dir(): string | null {
const os = getOS();
switch (os) {
case "linux": {
const xdg = getEnv("XDG_CONFIG_HOME");
if (xdg) return xdg;
const home = getEnv("HOME");
if (home) return `${home}/.config`;
break;
}
case "darwin": {
const home = getEnv("HOME");
if (home) return `${home}/Library/Preferences`;View on GitHub (pinned to e474e8803c)
Solutions
- Inspect the path: `ls -la` / `stat` the reported config location and check what is there
- If it is a stale/unused file, delete or rename it (`mv file file.bak`) and retry
- If it holds needed config, move the file contents into a directory of that name
- Fix the env var / flag so it points at a directory, not a file
- Check for a bad symlink (`readlink`) and repoint it
Example fix
// before WINDMILL_CONFIG_DIR=~/.windmill.yaml wmill sync pull // path is a file -> throws // after mkdir -p ~/.windmill && mv ~/.windmill.yaml ~/.windmill/config.yaml WINDMILL_CONFIG_DIR=~/.windmill wmill sync pull
Defensive patterns
Strategy: validation
Validate before calling
import { statSync } from 'node:fs';
function assertConfigDirWritable(p: string): void {
const st = statSync(p);
if (!st.isDirectory()) {
throw new Error(`${p} exists and is not a directory; move it aside first`);
}
} Type guard
function isDirectory(p: string): boolean {
try { return statSync(p).isDirectory(); } catch { return false; }
} Try / catch
try {
ensureDir(configPath);
} catch (e) {
if ((e as Error).message === 'Path is not a directory') {
console.error(`${configPath} is a file — rename it and retry`);
process.exit(1);
}
throw e;
} Prevention
- Point config-dir env vars/flags at directories, never at files
- Check existing paths with `stat` before configuring WINDMILL_CONFIG_DIR
- In Docker, mount config paths as named volumes/directories, not single files
When it happens
Trigger: Calling `ensureDir` on a config path where a regular file already exists at that exact path; a stale file named like the config directory (e.g. `$WINDMILL_CONFIG_DIR` or the OS config dir resolves to a file); a symlink pointing to a file.
Common situations: Users set an env var pointing the CLI at a file (accidentally passing a config *file* path instead of a directory); Docker volume mounts that created a file where a directory was expected; interrupted tooling left a stray file named `windmill` in `~/.config`.
Related errors
- File not found: ${filePath}
- Workspace folder not found, are you in the right directory?
- Directory not found: ${targetDirectory}
- Path is not a directory: ${targetDirectory}
- file path must refer to a file.
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/a1f97bc62e46b077.
Report an issue: GitHub.