{"record":{"id":"08b5f210fa93bbfe","repo":"pulumi/pulumi","slug":"invalid-workdir-passed-to-local-workspace-work","errorCode":null,"errorMessage":"Invalid workDir passed to local workspace: '${workDir}' does not exist","messagePattern":"Invalid workDir passed to local workspace: '(.+?)' does not exist","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"sdk/nodejs/automation/localWorkspace.ts","lineNumber":367,"sourceCode":"        if (opts) {\n            const {\n                workDir,\n                pulumiHome,\n                program,\n                remoteExecutorImage,\n                envVars,\n                secretsProvider,\n                remote,\n                remoteGitProgramArgs,\n                remotePreRunCommands,\n                remoteEnvVars,\n                remoteSkipInstallDependencies,\n                remoteInheritSettings,\n            } = opts;\n            if (workDir) {\n                // Verify that the workdir exists.\n                if (!fs.existsSync(workDir)) {\n                    throw new Error(`Invalid workDir passed to local workspace: '${workDir}' does not exist`);\n                }\n                dir = workDir;\n            }\n            this.pulumiHome = pulumiHome;\n            this.remoteExecutorImage = remoteExecutorImage;\n            this.program = program;\n            this.secretsProvider = secretsProvider;\n            this.remote = remote;\n            this.remoteGitProgramArgs = remoteGitProgramArgs;\n            this.remotePreRunCommands = remotePreRunCommands;\n            this.remoteEnvVars = { ...remoteEnvVars };\n            this.remoteSkipInstallDependencies = remoteSkipInstallDependencies;\n            this.remoteInheritSettings = remoteInheritSettings;\n            envs = { ...envVars };\n        }\n\n        if (!dir) {\n            dir = fs.mkdtempSync(upath.joinSafe(os.tmpdir(), \"automation-\"));","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/sdk/nodejs/automation/localWorkspace.ts#L349-L385","documentation":"During LocalWorkspace setup (sdk/nodejs/automation/localWorkspace.ts:367), if `opts.workDir` is supplied the constructor verifies it exists with `fs.existsSync`; if not it throws `Invalid workDir passed to local workspace: '<workDir>' does not exist`. The Automation API refuses to build a workspace rooted at a missing directory.","triggerScenarios":"Passing `workDir` in `LocalWorkspaceOptions` (to LocalWorkspace.create, Stack.create, createOrSelectStack, etc.) pointing to a directory that does not exist at construction time — wrong relative path, typo, or directory deleted/not yet created in CI.","commonSituations":"Relative paths resolved against a different CWD in CI vs local; project checked out into a different path in CI; directory created later by a build step that hasn't run yet; typos like `./src` vs `./source`; running from a container where the path was never mounted.","solutions":["Create the directory before constructing the workspace: `fs.mkdirSync(workDir, { recursive: true })`.","Use absolute paths (`path.resolve(...)`) to avoid CWD ambiguity.","Verify the path exists: `fs.existsSync(workDir)` or `ls <workDir>` before running.","Fix typos in the configured path; check CI checkout/mount configuration.","If omitting `workDir`, the workspace defaults to the current directory — make sure CWD is correct."],"exampleFix":"// before\nawait LocalWorkspace.create({ stackName: \"dev\", workDir: \"./nonexistent/app\" });\n// after\nconst workDir = path.resolve(\"./app\");\nfs.mkdirSync(workDir, { recursive: true });\nawait LocalWorkspace.create({ stackName: \"dev\", workDir });","handlingStrategy":"validation","validationCode":"import fs from \"fs\";\nimport path from \"path\";\nconst workDir = path.resolve(process.env.PROJECT_DIR ?? \"./app\");\nif (!fs.existsSync(workDir)) fs.mkdirSync(workDir, { recursive: true });\n// then pass workDir to LocalWorkspaceOptions","typeGuard":"function isValidWorkDir(p: string): boolean {\n  return fs.existsSync(p) && fs.statSync(p).isDirectory();\n}","tryCatchPattern":"try {\n  const ws = await LocalWorkspace.create({ workDir });\n} catch (err) {\n  if (String(err).includes(\"Invalid workDir passed to local workspace\")) {\n    fs.mkdirSync(workDir, { recursive: true });\n    // retry creation\n  } else throw err;\n}","preventionTips":["Use absolute paths via path.resolve to avoid CWD surprises","Ensure checkout/build steps create the directory before automation runs","Check container volume mounts expose the path","Validate the path with fs.existsSync before constructing a workspace"],"tags":["typescript","automation-api","filesystem","path-validation"],"backgroundTag":"directory-not-found","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}