pulumi/pulumi · error

deleteBeforeReplace must be a boolean or null

Error message

deleteBeforeReplace must be a boolean or null

What it means

The deleteBeforeReplace resource option must evaluate to a boolean or null. This error is raised when the option evaluates to some other cty type (string, number, object). The interpreter only accepts IsBool values and otherwise fails with this message.

Source

Thrown at pkg/pcl/runtime/interpreter.go:1740

					Delete: timeoutValues["delete"],
					Read:   timeoutValues["read"],
				}
			}
		}
		if res.Options.DeleteBeforeReplace != nil {
			dbr, poison, diags := evalCtx.Evaluate(res.Options.DeleteBeforeReplace)
			if poison != nil {
				return makePoisonValue(*poison), nil
			}
			if diags.HasErrors() {
				return cty.NilVal, diags
			}
			if !dbr.IsNull() && !dbr.IsComputed() {
				if dbr.IsBool() {
					request.DeleteBeforeReplace = dbr.BoolValue()
					request.DeleteBeforeReplaceDefined = true
				} else if !dbr.IsNull() {
					return cty.NilVal, errors.New("deleteBeforeReplace must be a boolean or null")
				}
			}
		}
		if res.Options.DeletedWith != nil {
			deletedWith, poison, diags := evalCtx.Evaluate(res.Options.DeletedWith)
			if poison != nil {
				return makePoisonValue(*poison), nil
			}
			if diags.HasErrors() {
				return cty.NilVal, diags
			}
			if !deletedWith.IsNull() && !deletedWith.IsComputed() {
				urn, _, err := unwrapResource(deletedWith)
				if err != nil {
					return cty.NilVal, fmt.Errorf("deletedWith: %w", err)
				}
				request.DeletedWith = urn
			}

View on GitHub (pinned to 793f7b2e16)

Solutions

  1. Use a real boolean literal: options { deleteBeforeReplace: true }
  2. Remove quotes from boolean values inherited from JSON/YAML snippets
  3. If the value is dynamic, ensure the expression evaluates to a bool type, not a string

Example fix

// before
options = { deleteBeforeReplace: "true" }
// after
options = { deleteBeforeReplace: true }
Defensive patterns

Strategy: type-guard

Validate before calling

// Before running, reject non-bool deleteBeforeReplace
if v, ok := opts["deleteBeforeReplace"]; ok {
    switch v.(type) {
    case bool, nil:
    default:
        return fmt.Errorf("deleteBeforeReplace must be a bool or null, got %T", v)
    }
}

Type guard

func isBoolOrNil(v any) bool {
    switch v.(type) {
    case bool, nil:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: Passing options {deleteBeforeReplace: "true"} (string) or {deleteBeforeReplace: 1} to a resource in a PCL program evaluated by the PCL runtime (interpreter.go:1740).

Common situations: Copy-pasting options from YAML/JSON where booleans are quoted strings; interpolating a computed string into the option; typos like "yes"/"no".

Related errors


AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31). Data as JSON: /api/errors/8c4ba12af2cdaa76. Report an issue: GitHub.