Repository navigation
Local state: apply reports success but writes no state when the state file can't be created and -lock=false #39409
Description
Terraform Version
Terraform v1.18.0-dev
on darwin_arm64Built from main at 44fcc13 (2026-10-16). The code path involved has not changed since 53cafc5 (2018), so released versions should behave the same way.
Terraform Configuration Files
resource "terraform_data" "example" {
input = "hello"
}Debug Output
Relevant lines from TF_LOG=trace (timestamps stripped):
[TRACE] statemgr.Filesystem: preparing to manage state snapshots at ro/out.tfstate
[DEBUG] State storage *statemgr.Filesystem declined to persist a state snapshot
[TRACE] statemgr.Filesystem: reading initial snapshot from terraform.tfstate
[TRACE] statemgr.Filesystem: snapshot file has nil snapshot, but that's okay
[TRACE] statemgr.Filesystem: read nil snapshot
[TRACE] statemgr.Filesystem: preparing to manage state snapshots at ro/out.tfstate
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
State path: ro/out.tfstate
Expected Behavior
When the local state file can't be created or opened, terraform apply should fail with an error. Terraform's existing recovery path should then run: it reports "Failed to persist state to backend" and writes errored.tfstate. This is what already happens when locking is enabled, because Lock() calls the same createStateFiles() and returns its error.
Actual Behavior
With -lock=false, the apply creates the resource, prints Apply complete! and State path: ro/out.tfstate, and exits 0, but no state file is written anywhere. The created resource is now untracked, and nothing tells the user.
The cause is in internal/states/statemgr/filesystem.go, in (*Filesystem).writeState:
if s.stateFileOut == nil {
if err := s.createStateFiles(); err != nil {
return nil // error is discarded
}
}With locking enabled, Lock() calls createStateFiles() first and handles the error correctly. Without a lock, writeState is the first caller, so the error is swallowed and the method reports success.
Steps to Reproduce
mkdir repro && cd repro
cat > main.tf <<'EOF'
resource "terraform_data" "example" {
input = "hello"
}
EOF
mkdir ro && chmod 0555 ro
terraform init
terraform apply -auto-approve -lock=false -state-out=ro/out.tfstate
echo "exit=$?" # exit=0, "Apply complete!"
ls ro # empty: no state was writtenFor comparison, the same command without -lock=false fails correctly with Error acquiring the state lock ... open ro/out.tfstate: permission denied.
Additional Context
I tried the one-line change return nil → return err locally. The repro above then fails with Error: Failed to persist state to backend and writes errored.tfstate to the working directory, which is the intended recovery behaviour.
If the team agrees this is the right fix, I'd be happy to open a PR with it, plus a regression test in internal/states/statemgr/filesystem_test.go.
References
- tfstate file can be corrupted if operation cancelled #34266 is a related but separate local-state durability issue (non-atomic writes). This one is about the error being discarded entirely.
Generative AI / LLM assisted development?
Claude Code (Anthropic) was used to find this code path, reproduce it, and draft this report.
Activity