{"record":{"id":"a1f97bc62e46b077","repo":"windmill-labs/windmill","slug":"path-is-not-a-directory","errorCode":null,"errorMessage":"Path is not a directory","messagePattern":"Path is not a directory","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/windmill-utils-internal/src/config/config.ts","lineNumber":25,"sourceCode":"export const WINDMILL_ACTIVE_INSTANCE_FILE = \"activeInstance\";\n\nfunction getEnv(key: string): string | undefined {\n  return process.env[key];\n}\n\nfunction getOS(): \"linux\" | \"darwin\" | \"windows\" | null {\n  const platform = process.platform;\n  switch (platform) {\n    case \"linux\": return \"linux\";\n    case \"darwin\": return \"darwin\";\n    case \"win32\": return \"windows\";\n    default: return null;\n  }\n}\n\nfunction throwIfNotDirectory(fileInfo: import(\"node:fs\").Stats): void {\n  if (!fileInfo.isDirectory()) {\n    throw new Error(\"Path is not a directory\");\n  }\n}\n\nfunction config_dir(): string | null {\n  const os = getOS();\n  switch (os) {\n    case \"linux\": {\n      const xdg = getEnv(\"XDG_CONFIG_HOME\");\n      if (xdg) return xdg;\n\n      const home = getEnv(\"HOME\");\n      if (home) return `${home}/.config`;\n      break;\n    }\n\n    case \"darwin\": {\n      const home = getEnv(\"HOME\");\n      if (home) return `${home}/Library/Preferences`;","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/cli/windmill-utils-internal/src/config/config.ts#L7-L43","documentation":"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.","triggerScenarios":"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.","commonSituations":"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`.","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"],"exampleFix":"// before\nWINDMILL_CONFIG_DIR=~/.windmill.yaml wmill sync pull  // path is a file -> throws\n\n// after\nmkdir -p ~/.windmill && mv ~/.windmill.yaml ~/.windmill/config.yaml\nWINDMILL_CONFIG_DIR=~/.windmill wmill sync pull","handlingStrategy":"validation","validationCode":"import { statSync } from 'node:fs';\nfunction assertConfigDirWritable(p: string): void {\n  const st = statSync(p);\n  if (!st.isDirectory()) {\n    throw new Error(`${p} exists and is not a directory; move it aside first`);\n  }\n}","typeGuard":"function isDirectory(p: string): boolean {\n  try { return statSync(p).isDirectory(); } catch { return false; }\n}","tryCatchPattern":"try {\n  ensureDir(configPath);\n} catch (e) {\n  if ((e as Error).message === 'Path is not a directory') {\n    console.error(`${configPath} is a file — rename it and retry`);\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["filesystem","config","cli"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}