pulumi/pulumi · error
protect must be a boolean or null
Error message
protect must be a boolean or null
What it means
The PCL interpreter evaluates the `protect` resource option and requires it to be a boolean or null. Any other concrete type (string "true", number, object) triggers this error and stops evaluation of the resource registration.
Source
Thrown at pkg/pcl/runtime/interpreter.go:1593
}
request.IgnoreChanges = icopt
}
}
if res.Options.Protect != nil {
protect, poison, diags := evalCtx.Evaluate(res.Options.Protect)
if poison != nil {
return makePoisonValue(*poison), nil
}
if diags.HasErrors() {
return cty.NilVal, diags
}
if !protect.IsComputed() {
var popt *bool
if protect.IsBool() {
b := protect.BoolValue()
popt = &b
} else if !protect.IsNull() {
return cty.NilVal, errors.New("protect must be a boolean or null")
}
request.Protect = popt
}
}
if res.Options.ReplaceWith != nil {
replaceWith, poison, diags := evalCtx.Evaluate(res.Options.ReplaceWith)
if poison != nil {
return makePoisonValue(*poison), nil
}
if diags.HasErrors() {
return cty.NilVal, diags
}
if !replaceWith.IsNull() && !replaceWith.IsComputed() {
if !replaceWith.IsArray() {
return cty.NilVal, errors.New("replaceWith must be an array of resources")
}
var rwopt []string
for _, v := range replaceWith.ArrayValue() {View on GitHub (pinned to 793f7b2e16)
Solutions
- Use a bare boolean literal: protect = true or protect = false.
- Unquote string booleans: "true" -> true.
- Convert upstream strings to bools before passing (e.g. in the producing code or with a boolean-typed variable).
- Pass null (or omit/leave computed) if protection is conditional at runtime.
Example fix
// before (PCL)
options { protect = "true" }
// after
options { protect = true } Defensive patterns
Strategy: type-guard
Validate before calling
func validateProtect(v any) error {
switch t := v.(type) {
case nil, bool:
return nil
default:
return fmt.Errorf("protect must be bool, got %T", t)
}
} Type guard
func isBoolOrNull(v cty.Value) bool {
return v.IsNull() || v.Type() == cty.Bool
} Try / catch
if err != nil && strings.Contains(err.Error(), "protect must be a boolean or null") {
return fmt.Errorf("check the 'protect' option: use unquoted true/false: %w", err)
} Prevention
- Never quote boolean options ("true" is invalid).
- Use 0/1-free boolean types when migrating from YAML.
- Keep protect bound to bool-typed variables only.
- Omit or pass null instead of placeholders.
When it happens
Trigger: Passing `options { protect = "true" }` (string) or any non-bool, non-null value in `__opts.protect` to registerResource in pkg/pcl/runtime.
Common situations: Users quoting booleans when converting from YAML/JSON configs (`protect: "false"`), or binding protect to a variable typed as string instead of bool.
Related errors
- ignoreChanges must be an array of strings
- replaceWith must be an array of resources
- replaceWith: %w
- replaceOnChanges must be an array of strings
- retainOnDelete must be a boolean or null
AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31).
Data as JSON: /api/errors/47a8bb1940d15178.
Report an issue: GitHub.