Loading...
Loading...
### Terraform Version ```shell Terraform v1.16.0 on linux_amd64 Also reproduced on v1.17.0-alpha20260827. Not a regression: this has never worked. Resource-level lifecycle { destroy = false } landed between 1.16.0-alpha20260624 and 1.16.0-alpha20260708, and this combination has failed in every build that accepts the argument. ``` ### Terraform Configuration Files ```bash #!/usr/bin/env bash # Usage: ./repro.sh [path/to/terraform] (defaults to `terraform` on PATH) set -euo pipefail TF="${1:-terraform}" cd "$(mktemp -d)" cat > main.tf <<'EOF' resource "terraform_data" "r1" { triggers_replace = ["v1"] lifecycle { destroy = false create_before_destroy = true } } EOF "$TF" version "$TF" init -input=false > /dev/null "$TF" apply -auto-approve -input=false > /dev/null echo "step 1 applied." sed -i 's/\["v1"\]/["v2"]/' main.tf # force a replacement of r1 echo "step 2, replacing r1:" "$TF" apply -auto-approve -input=false -no-color ``` ### Debug Output `TF_LOG=trace` for the full reproduction, both applies: https://gist.github.com/Nilsils/7c0e60d4d200f81f3f9a0a66a9fe37ee The chain, in order (line numbers from that gist): ``` 968 DiffTransformer: terraform_data.r1 deposed object 8e7cdf03 will be represented for destruction by terraform_data.r1 (destroy deposed 8e7cdf03) 1223 managedResourceExecute: prior object for terraform_data.r1 now deposed with key 59b21c91 1254 (Unknown action Forget for terraform_data.r1 (deposed object 59b21c91)) 1259 terraform_data.r1: applying the planned Forget change 1262 vertex "terraform_data.r1 (destroy deposed 59b21c91)" error: Provider returned invalid result object after apply ``` Line 968 is the point of interest: the deposed object is represented by a `NodeDestroyDeposedResourceInstanceObject`, i.e. a node whose purpose is to **destroy** it. At 1259 that node is asked to apply a `Forget` instead, which it has no handler for. ### Expected Behavior terraform_data.r1 is replaced. Either the prior object is destroyed, or, if destroy = false means it should be released from state rather than destroyed, it is forgotten and the apply completes. Either way the apply succeeds. Removing either flag gives a clean Apply complete! Resources: 1 added, 0 changed, 1 destroyed. ### Actual Behavior The second apply fails: ``` (Unknown action Forget for terraform_data.r1 (deposed object 59b21c91)) Error: Provider returned invalid result object after apply After applying a Forget plan, the provider returned a null object for terraform_data.r1. Only destroying should always produce a null value, so this is always a bug in the provider and should be reported in the provider's own repository. ``` `create_before_destroy` makes the replacement **depose** the prior object rather than destroy it. `destroy = false` then applies to that deposed object, so Terraform plans `Forget` for it. The node representing it is a `NodeDestroyDeposedResourceInstanceObject` — a destroyer — and it has no handler for `Forget`, so the apply aborts. The deposed slot is transient by design: it holds an object between "the replacement has been created" and "the old one has been destroyed", and destroy is the only action ever scheduled against it. `destroy = false` asks for the one thing that slot cannot do. The diagnostic is misleading in two ways. The plan/apply mismatch originates in Terraform Core, not in a provider; and the "provider" named is `terraform_data`, which is built into Terraform and has no repository of its own to file against. The same failure occurs when `create_before_destroy` is not written on the resource at all but is **propagated** to it from a dependent that declares it — so a resource whose author wrote only `destroy = false` can hit this. Nothing is leaked: the apply aborts rather than silently skipping the destroy. ### Steps to Reproduce 1. Save the script above as `repro.sh`. 2. Run it: ``` $ bash repro.sh # uses `terraform` from PATH $ bash repro.sh /path/to/terraform # or name a binary ``` ### Additional Context _No response_ ### References - #39076 same subsystem, different defect. That one is a regression in `alpha20260715` whose symptom is a silently skipped destroy; this reproduces on `alpha20260708` and fails loudly. ### Generative AI / LLM assisted development? The configuration was not written by an LLM. It was produced by an automated metamorphic testing pipeline (an e-graph based generator of equivalent Terraform programs), then minimised to the form above. Claude was used to assist with the writing of this report, with the reduction, and with the version sweep. Every claim in it was verified by running the configurations.
Click on a version to see all relevant bugs
Terraform Integration
Learn more about where this data comes from
BugZero Plan
Streamline upgrades with automated vendor bug scrubs
BugZero Prevent
Wish you caught this bug sooner? Get proactive today.