opentofu/opentofu

`run.*` references resolve to empty object after `command = plan` run blocks in `tofu test`

Open

#3754 opened on Feb 11, 2026

View on GitHub
 (2 comments) (1 reaction) (0 assignees)Go (28,648 stars) (1,237 forks)batch import
acceptedenhancementhelp wantedneeds-rfctest-command

Description

Community note

[!TIP] 👋 Hi there, OpenTofu community! The OpenTofu team prioritizes issues based on upvotes. Please make sure to upvote this issue and describe how it affects you in detail in the comments to show your support.

OpenTofu Version

1.11.x

OpenTofu Configuration Files

 # main.tf
output "name" {
  value = "test-plan"
}

# other/main.tf
variable "name" { # This is important!
  type = string
}

output "received_name" {
  value = var.name
}

# main.tftest.hcl
run "setup" {
  command = plan
}

run "use_output" {
  command = plan

  variables {
    name = run.setup.name # This should work?
  }

  module {
    source = "./other"
  }

  assert {
    condition     = output.received_name == "test-plan"
    error_message = "expected received_name to be 'test-plan', got '${output.received_name}'"
  }
}

Debug Output

   main.tftest.hcl... fail
     run "setup"... pass
     run "use_output"... fail
   ╷
   │ Error: Unsupported attribute
   │
   │   on main.tftest.hcl line 9, in run "use_output":
   │    9:     name = run.setup.name
   │     ├────────────────
   │     │ run is object with no attributes
   │
   │ This object does not have an attribute named "setup".
   ╵

Expected Behavior

run.* references should resolve to planned output values after a command = plan run block, the same way they do after command = apply.

Actual Behavior

The tests are failing, run,* references are not constructed properly

Steps to Reproduce

  1. tofu init
  2. tofu test

Additional Context

When a run block is using command = plan the ExecuteTestRun method returns state, false here https://github.com/opentofu/opentofu/blob/1e0a920a3418eded87bf55990e2762fb41e6ed78/internal/command/test.go#L620

The false here means that we are instructing the runner that we have NOT updated the state. This means that we never implement the serialization of data between runs here https://github.com/opentofu/opentofu/blob/1e0a920a3418eded87bf55990e2762fb41e6ed78/internal/command/test.go#L506-L511

Because we never populate this runner.States for plan, the run object is not constructed correctly for command = plan run blocks.

References

Slack conversation in the CNCF Slack #opentofu channel https://cloud-native.slack.com/archives/C05PXGAB05R/p1770793367607299

Contributor guide