pulumi/pulumi · error · ErrSaveStackConfig
saving stack config
Error message
saving stack config
What it means
ErrSaveStackConfig is a sentinel wrapping errors from SaveProjectStack that occur inside CreateStack after the backend stack has already been created successfully. Callers detect it with errors.Is(err, ErrSaveStackConfig) to know the backend stack exists despite the error, so it can be cleaned up or retried safely.
Source
Thrown at pkg/cmd/pulumi/stack/io.go:372
}
// InitStack creates the stack.
func InitStack(
ctx context.Context, sink diag.Sink, ws pkgWorkspace.Context, b backend.Backend, stackName string,
root string, opts CreateStackOptions,
) (backend.Stack, error) {
stackRef, err := b.ParseStackReference(stackName)
if err != nil {
return nil, err
}
return CreateStack(ctx, sink, ws, b, stackRef, root, opts)
}
// ErrSaveStackConfig wraps `SaveProjectStack` errors that occur in `CreateStack` after the
// backend stack has already been successfully created. Callers can detect this case via
// `errors.Is(err, ErrSaveStackConfig)` to know that the backend stack exists despite the error
// (e.g. so they can clean it up).
var ErrSaveStackConfig = errors.New("saving stack config")
// CreateStack creates a stack with the given name, and optionally selects it as the current.
func CreateStack(ctx context.Context, sink diag.Sink, ws pkgWorkspace.Context,
b backend.Backend, stackRef backend.StackReference, root string, opts CreateStackOptions,
) (backend.Stack, error) {
ps, needsSave, sm, err := createSecretsManagerForNewStack(
ctx, sink, ws, b, stackRef, opts.SecretsProvider, opts.ConfigFile)
if err != nil {
return nil, fmt.Errorf("could not create secrets manager for new stack: %w", err)
}
// If we have a non-empty secrets manager, we'll send it off to the backend as part of the initial state to be stored
// for the stack.
var initialState *apitype.UntypedDeployment
if sm != nil {
m := deploy.Manifest{
Time: time.Now(),
Version: version.Version,View on GitHub (pinned to 793f7b2e16)
Solutions
- Note the backend stack WAS created; delete or reuse it before retrying (errors.Is(err, ErrSaveStackConfig))
- Check write permissions on the project directory and the target config file
- Validate Pulumi.yaml (or the --config-file target) is well-formed YAML and writable
- Free disk space / close programs locking the file, then retry
Example fix
if err := pulumiCreateStack(...); err != nil {
if errors.Is(err, iostack.ErrSaveStackConfig) {
// backend stack exists despite save failure — clean up or proceed
log.Println("stack exists on backend; fixing local config only")
}
} Defensive patterns
Strategy: type-guard
Validate before calling
// ensure the project config file is writable before creating
info, err := os.Stat(filepath.Join(root, "Pulumi.yaml"))
if err == nil && info.Mode().Perm()&0200 == 0 {
return errors.New("Pulumi.yaml is not writable")
} Type guard
func isSaveStackConfigErr(err error) bool {
return errors.Is(err, iostack.ErrSaveStackConfig)
} Try / catch
if err != nil {
if errors.Is(err, iostack.ErrSaveStackConfig) {
// backend stack exists despite save failure: cleanup or adopt
b.DeleteStack(ctx, ref)
}
return err
} Prevention
- Run stack creation in writable working directories
- Validate Pulumi.yaml parses before programmatic stack creation
- Check --config-file target exists and is writable
When it happens
Trigger: CreateStack succeeds on the backend, needsSave is true, and SaveProjectStack then fails — e.g. the project stack config file (Pulumi.yaml) is unwritable, malformed, or the write path is invalid.
Common situations: Read-only working directory or repo checkout, Pulumi.yaml corrupted/locked by another process, wrong --config-file path pointing outside the project, or disk-full conditions.
Related errors
- saving stack config: %w
- getting current working directory: %w
- error starting pulumi-watch: %w
- Could not locate an executable pulumi-watch, found %v withou
- writing temporary file: %w
AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31).
Data as JSON: /api/errors/edb6ed6520eb1f62.
Report an issue: GitHub.