{"record":{"id":"ab4275e327bc7277","repo":"pulumi/pulumi","slug":"resolving-pulumi-cwd-w","errorCode":null,"errorMessage":"resolving pulumi cwd: %w","messagePattern":"resolving pulumi cwd: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/cmd/pulumi/neo/tools/pulumi.go","lineNumber":115,"sourceCode":"\tOnDiag func(toolName, severity, message, urn string)\n\t// OnEnd finalizes the block. err is empty on success, otherwise the\n\t// wrapped engine error string. counts is the typed ResourceChanges map\n\t// from the engine.\n\tOnEnd func(toolName, err string, counts display.ResourceChanges, elapsed string)\n}\n\n// NewPulumi creates a Pulumi handler sandboxed under cwd. The workspace is captured\n// at construction so tests can inject a fake; the backend is resolved fresh on each\n// tool call (see run). Sink may be nil when running outside the interactive TUI\n// (non-interactive mode); in that case progress is silently dropped and the final\n// result is still returned to the caller.\nfunc NewPulumi(cwd string, ws pkgWorkspace.Context, sink *PulumiSink) (*Pulumi, error) {\n\tif ws == nil {\n\t\treturn nil, errors.New(\"workspace is required\")\n\t}\n\tabs, err := canonicalRoot(cwd)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"resolving pulumi cwd: %w\", err)\n\t}\n\treturn &Pulumi{Cwd: abs, Workspace: ws, Sink: sink}, nil\n}\n\n// pulumiArgs matches pulumi-service:cmd/agents/src/agents_py/mcp/pulumi_mcp.py's\n// pulumi_preview/pulumi_up parameters.\ntype pulumiArgs struct {\n\tProjectName          string            `json:\"project_name\"`\n\tStackName            string            `json:\"stack_name\"`\n\tLocalPulumiDir       string            `json:\"local_pulumi_dir\"`\n\tEnvironmentVariables map[string]envVal `json:\"environment_variables,omitempty\"`\n}\n\n// envVal decodes the dict value type `str | SecretValue` used by the upstream schema.\n// Plain and Secret are mutually exclusive; the Value() accessor returns whichever is set.\n// Secret values must never be echoed into logs, progress messages, or the events file.\ntype envVal struct {\n\tPlain  string","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/pkg/cmd/pulumi/neo/tools/pulumi.go#L97-L133","documentation":"NewPulumi canonicalizes the given cwd via canonicalRoot before storing it; if that fails (path cannot be made absolute/resolved, e.g. nonexistent directory or unreadable ancestor), the error is wrapped as 'resolving pulumi cwd: %w'. The Pulumi tool refuses to construct with an unusable working directory since all subsequent operations depend on it.","triggerScenarios":"Calling NewPulumi with a cwd that does not exist, is a file rather than a directory, has a broken symlink ancestor, or cannot be canonicalized due to permissions.","commonSituations":"Passing a project directory path from stale configuration after the directory was moved/deleted; symlinked workspaces whose target vanished; containers started with a workdir that was replaced at runtime; relative cwd strings while the process cwd is invalid.","solutions":["Verify the cwd exists and is a directory before calling NewPulumi (os.Stat).","Update the configured project directory to the current actual location of the workspace.","Pass an absolute, existing path; resolve symlinks yourself if the workspace path is a link.","Fix permissions on ancestor directories so canonicalRoot can traverse them."],"exampleFix":"// before\np, err := NewPulumi(\"/old/deleted/project\", ws, sink)\n// after\nif _, err := os.Stat(\"/current/project\"); err == nil {\n    p, err := NewPulumi(\"/current/project\", ws, sink)\n}","handlingStrategy":"validation","validationCode":"fi, err := os.Stat(cwd)\nif err != nil {\n    return fmt.Errorf(\"cwd %s does not exist: %w\", cwd, err)\n}\nif !fi.IsDir() {\n    return fmt.Errorf(\"cwd %s is not a directory\", cwd)\n}","typeGuard":null,"tryCatchPattern":"p, err := NewPulumi(cwd, ws, sink)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"resolving pulumi cwd:\") {\n        return fmt.Errorf(\"check configured project directory %q: %w\", cwd, err)\n    }\n    return err\n}","preventionTips":["Stat the cwd and confirm it is an existing directory before calling NewPulumi","Keep project-directory configuration in sync when workspaces move","Resolve symlinked workspace paths to real targets beforehand","Pass absolute cwd paths so invalid process working directories don't matter"],"tags":["configuration","path-resolution","pulumi"],"backgroundTag":"invalid-working-directory","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}