pulumi/pulumi · error
resolving pulumi cwd: %w
Error message
resolving pulumi cwd: %w
What it means
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.
Source
Thrown at pkg/cmd/pulumi/neo/tools/pulumi.go:115
OnDiag func(toolName, severity, message, urn string)
// OnEnd finalizes the block. err is empty on success, otherwise the
// wrapped engine error string. counts is the typed ResourceChanges map
// from the engine.
OnEnd func(toolName, err string, counts display.ResourceChanges, elapsed string)
}
// NewPulumi creates a Pulumi handler sandboxed under cwd. The workspace is captured
// at construction so tests can inject a fake; the backend is resolved fresh on each
// tool call (see run). Sink may be nil when running outside the interactive TUI
// (non-interactive mode); in that case progress is silently dropped and the final
// result is still returned to the caller.
func NewPulumi(cwd string, ws pkgWorkspace.Context, sink *PulumiSink) (*Pulumi, error) {
if ws == nil {
return nil, errors.New("workspace is required")
}
abs, err := canonicalRoot(cwd)
if err != nil {
return nil, fmt.Errorf("resolving pulumi cwd: %w", err)
}
return &Pulumi{Cwd: abs, Workspace: ws, Sink: sink}, nil
}
// pulumiArgs matches pulumi-service:cmd/agents/src/agents_py/mcp/pulumi_mcp.py's
// pulumi_preview/pulumi_up parameters.
type pulumiArgs struct {
ProjectName string `json:"project_name"`
StackName string `json:"stack_name"`
LocalPulumiDir string `json:"local_pulumi_dir"`
EnvironmentVariables map[string]envVal `json:"environment_variables,omitempty"`
}
// envVal decodes the dict value type `str | SecretValue` used by the upstream schema.
// Plain and Secret are mutually exclusive; the Value() accessor returns whichever is set.
// Secret values must never be echoed into logs, progress messages, or the events file.
type envVal struct {
Plain stringView on GitHub (pinned to 793f7b2e16)
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.
Example fix
// before
p, err := NewPulumi("/old/deleted/project", ws, sink)
// after
if _, err := os.Stat("/current/project"); err == nil {
p, err := NewPulumi("/current/project", ws, sink)
} Defensive patterns
Strategy: validation
Validate before calling
fi, err := os.Stat(cwd)
if err != nil {
return fmt.Errorf("cwd %s does not exist: %w", cwd, err)
}
if !fi.IsDir() {
return fmt.Errorf("cwd %s is not a directory", cwd)
} Try / catch
p, err := NewPulumi(cwd, ws, sink)
if err != nil {
if strings.HasPrefix(err.Error(), "resolving pulumi cwd:") {
return fmt.Errorf("check configured project directory %q: %w", cwd, err)
}
return err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- cannot refresh stacks with remote config
- getting configuration file: %w
- getting latest configuration: %w
- resolving stack: %w
- workspace is required
AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31).
Data as JSON: /api/errors/ab4275e327bc7277.
Report an issue: GitHub.