Skip to content

terraform plan -detailed-exitcode returns exit code 2 while displaying "No changes" when output expression type changes #38097

@AkashiSN

Description

@AkashiSN

Terraform Version

Terraform v1.14.3 and v1.15.0-alpha20251203

Terraform Configuration Files

# main.tf
locals {
    empty_list = tolist([])
}

output "result" {
    value = {
        items = length(local.empty_list) > 0 ? local.empty_list : [""]
    }
}

After initial apply, change to:

# main.tf (modified)
output "result" {
    value = {
        items = [""]
    }
}

Debug Output

2026-01-26T23:56:58.245+0900 [INFO]  Terraform version: 1.14.3
2026-01-26T23:56:58.245+0900 [DEBUG] using github.com/hashicorp/go-tfe v1.94.0
2026-01-26T23:56:58.245+0900 [DEBUG] using github.com/hashicorp/hcl/v2 v2.24.0
2026-01-26T23:56:58.245+0900 [DEBUG] using github.com/hashicorp/terraform-svchost v0.1.1
2026-01-26T23:56:58.245+0900 [DEBUG] using github.com/zclconf/go-cty v1.16.3
2026-01-26T23:56:58.245+0900 [INFO]  Go runtime version: go1.25.5
2026-01-26T23:56:58.245+0900 [INFO]  CLI args: []string{"/Users/user/.tenv/Terraform/1.14.3/terraform", "plan", "-detailed-exitcode"}
2026-01-26T23:56:58.245+0900 [TRACE] Stdout is a terminal of width 197
2026-01-26T23:56:58.245+0900 [TRACE] Stderr is a terminal of width 197
2026-01-26T23:56:58.245+0900 [TRACE] Stdin is a terminal
2026-01-26T23:56:58.245+0900 [DEBUG] Attempting to open CLI config file: /Users/user/.terraformrc
2026-01-26T23:56:58.245+0900 [DEBUG] File doesn't exist, but doesn't need to. Ignoring.
2026-01-26T23:56:58.245+0900 [DEBUG] ignoring non-existing provider search directory terraform.d/plugins
2026-01-26T23:56:58.245+0900 [DEBUG] ignoring non-existing provider search directory /Users/user/.terraform.d/plugins
2026-01-26T23:56:58.245+0900 [DEBUG] ignoring non-existing provider search directory /Users/user/Library/Application Support/io.terraform/plugins
2026-01-26T23:56:58.245+0900 [DEBUG] ignoring non-existing provider search directory /Library/Application Support/io.terraform/plugins
2026-01-26T23:56:58.245+0900 [INFO]  CLI command args: []string{"plan", "-detailed-exitcode"}
2026-01-26T23:56:58.246+0900 [TRACE] Meta.Backend: no config given or present on disk, so returning nil config
2026-01-26T23:56:58.246+0900 [TRACE] Meta.Backend: backend has not previously been initialized in this working directory
2026-01-26T23:56:58.246+0900 [TRACE] Meta.Backend: using default local state only (no backend configuration, and no existing initialized backend)
2026-01-26T23:56:58.246+0900 [TRACE] Meta.Backend: instantiated backend of type <nil>
2026-01-26T23:56:58.246+0900 [DEBUG] checking for provisioner in "."
2026-01-26T23:56:58.246+0900 [DEBUG] checking for provisioner in "/Users/user/.tenv/Terraform/1.14.3"
2026-01-26T23:56:58.246+0900 [TRACE] Meta.Backend: backend <nil> does not support operations, so wrapping it in a local backend
2026-01-26T23:56:58.247+0900 [INFO]  backend/local: starting Plan operation
2026-01-26T23:56:58.247+0900 [TRACE] backend/local: requesting state manager for workspace "default"
2026-01-26T23:56:58.247+0900 [TRACE] backend/local: state manager for workspace "default" will:
 - read initial snapshot from terraform.tfstate
 - write new snapshots to terraform.tfstate
 - create any backup at terraform.tfstate.backup
2026-01-26T23:56:58.247+0900 [TRACE] backend/local: requesting state lock for workspace "default"
2026-01-26T23:56:58.248+0900 [TRACE] statemgr.Filesystem: preparing to manage state snapshots at terraform.tfstate
2026-01-26T23:56:58.248+0900 [TRACE] statemgr.Filesystem: existing snapshot has lineage "5fdcb357-d831-c31f-a57e-34771b229a62" serial 1
2026-01-26T23:56:58.248+0900 [TRACE] statemgr.Filesystem: locking terraform.tfstate using fcntl flock
2026-01-26T23:56:58.248+0900 [TRACE] statemgr.Filesystem: writing lock metadata to .terraform.tfstate.lock.info
2026-01-26T23:56:58.248+0900 [TRACE] backend/local: reading remote state for workspace "default"
2026-01-26T23:56:58.248+0900 [TRACE] statemgr.Filesystem: reading latest snapshot from terraform.tfstate
2026-01-26T23:56:58.249+0900 [TRACE] statemgr.Filesystem: read snapshot with lineage "5fdcb357-d831-c31f-a57e-34771b229a62" serial 1
2026-01-26T23:56:58.249+0900 [TRACE] backend/local: populating backendrun.LocalRun for current working directory
2026-01-26T23:56:58.249+0900 [TRACE] terraform.NewContext: starting
2026-01-26T23:56:58.249+0900 [TRACE] terraform.NewContext: complete
2026-01-26T23:56:58.249+0900 [TRACE] backend/local: requesting interactive input, if necessary
2026-01-26T23:56:58.249+0900 [TRACE] Context.Input: Prompting for provider arguments
2026-01-26T23:56:58.249+0900 [TRACE] backend/local: running validation operation
2026-01-26T23:56:58.249+0900 [DEBUG] Building and walking validate graph
2026-01-26T23:56:58.249+0900 [TRACE] building graph for walkValidate
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.ConfigTransformer
2026-01-26T23:56:58.249+0900 [TRACE] ConfigTransformer: Starting for path:
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.ActionTriggerConfigTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.ActionInvokePlanTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.RootVariableTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.ModuleVariableTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.variableValidationTransformer
2026-01-26T23:56:58.249+0900 [TRACE] variableValidationTransformer: adding validation nodes for any existing variable evaluation nodes
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.LocalTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.OutputTransformer
2026-01-26T23:56:58.249+0900 [TRACE] OutputTransformer: adding result as *terraform.nodeExpandOutput
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.checkTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.OrphanResourceInstanceTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.StateTransformer
2026-01-26T23:56:58.249+0900 [TRACE] StateTransformer: pointless no-op call, creating no nodes at all
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.AttachStateTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.OrphanOutputTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.AttachResourceConfigTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.graphTransformerMulti
2026-01-26T23:56:58.249+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.externalProviderTransformer
2026-01-26T23:56:58.249+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.externalProviderTransformer with new graph:
  local.empty_list (expand) - *terraform.nodeExpandLocal
  output.result (expand) - *terraform.nodeExpandOutput
  ------
2026-01-26T23:56:58.249+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.ProviderConfigTransformer
2026-01-26T23:56:58.249+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.ProviderConfigTransformer (no changes)
2026-01-26T23:56:58.249+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.MissingProviderTransformer
2026-01-26T23:56:58.249+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.MissingProviderTransformer (no changes)
2026-01-26T23:56:58.249+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.ProviderTransformer
2026-01-26T23:56:58.249+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.ProviderTransformer (no changes)
2026-01-26T23:56:58.249+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.PruneProviderTransformer
2026-01-26T23:56:58.249+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.PruneProviderTransformer (no changes)
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.RemovedModuleTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.AttachSchemaTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.ModuleExpansionTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.ExternalReferenceTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.ReferenceTransformer
2026-01-26T23:56:58.249+0900 [DEBUG] ReferenceTransformer: "output.result (expand)" references: []
2026-01-26T23:56:58.249+0900 [DEBUG] ReferenceTransformer: "local.empty_list (expand)" references: []
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.AttachDependenciesTransformer
2026-01-26T23:56:58.249+0900 [TRACE] AttachDependenciesTransformer: output.result (expand) depends on []
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.attachDataResourceDependsOnTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.DestroyEdgeTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.pruneUnusedNodesTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.TargetsTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.QueryTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.ForcedCBDTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.ephemeralResourceCloseTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.CloseProviderTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.CloseRootModuleTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.TransitiveReductionTransformer
2026-01-26T23:56:58.249+0900 [TRACE] Completed graph transform:
local.empty_list (expand) - *terraform.nodeExpandLocal
output.result (expand) - *terraform.nodeExpandOutput
root - *terraform.nodeCloseModule
  local.empty_list (expand) - *terraform.nodeExpandLocal
  output.result (expand) - *terraform.nodeExpandOutput
  ------
2026-01-26T23:56:58.249+0900 [DEBUG] Starting graph walk: walkValidate
2026-01-26T23:56:58.249+0900 [TRACE] vertex "output.result (expand)": starting visit (*terraform.nodeExpandOutput)
2026-01-26T23:56:58.249+0900 [TRACE] vertex "output.result (expand)": does not belong to any module instance
2026-01-26T23:56:58.249+0900 [TRACE] vertex "local.empty_list (expand)": starting visit (*terraform.nodeExpandLocal)
2026-01-26T23:56:58.249+0900 [TRACE] vertex "local.empty_list (expand)": does not belong to any module instance
2026-01-26T23:56:58.249+0900 [TRACE] vertex "local.empty_list (expand)": expanding dynamic subgraph
2026-01-26T23:56:58.249+0900 [TRACE] Expanding local: adding local.empty_list as *terraform.NodeLocal
2026-01-26T23:56:58.249+0900 [TRACE] vertex "local.empty_list (expand)": entering dynamic subgraph
2026-01-26T23:56:58.249+0900 [TRACE] vertex "output.result (expand)": expanding dynamic subgraph
2026-01-26T23:56:58.249+0900 [TRACE] Expanding output: adding output.result as *terraform.NodeApplyableOutput
2026-01-26T23:56:58.249+0900 [TRACE] vertex "output.result (expand)": entering dynamic subgraph
2026-01-26T23:56:58.249+0900 [TRACE] vertex "local.empty_list": starting visit (*terraform.NodeLocal)
2026-01-26T23:56:58.249+0900 [TRACE] vertex "local.empty_list": belongs to
2026-01-26T23:56:58.249+0900 [TRACE] vertex "output.result": starting visit (*terraform.NodeApplyableOutput)
2026-01-26T23:56:58.249+0900 [TRACE] vertex "output.result": belongs to
2026-01-26T23:56:58.249+0900 [TRACE] vertex "local.empty_list": visit complete
2026-01-26T23:56:58.249+0900 [TRACE] setValue: Saving Create change for output.result in changeset
2026-01-26T23:56:58.249+0900 [TRACE] vertex "root": starting visit (terraform.graphNodeRoot)
2026-01-26T23:56:58.249+0900 [TRACE] vertex "root": does not belong to any module instance
2026-01-26T23:56:58.249+0900 [TRACE] vertex "root": visit complete
2026-01-26T23:56:58.249+0900 [TRACE] vertex "local.empty_list (expand)": dynamic subgraph completed successfully
2026-01-26T23:56:58.249+0900 [TRACE] vertex "local.empty_list (expand)": visit complete
2026-01-26T23:56:58.249+0900 [TRACE] setValue: Saving value for output.result in state
2026-01-26T23:56:58.249+0900 [TRACE] setValue: Saving value for output.result in state
2026-01-26T23:56:58.249+0900 [TRACE] vertex "output.result": visit complete
2026-01-26T23:56:58.249+0900 [TRACE] vertex "root": starting visit (terraform.graphNodeRoot)
2026-01-26T23:56:58.249+0900 [TRACE] vertex "root": does not belong to any module instance
2026-01-26T23:56:58.249+0900 [TRACE] vertex "root": visit complete
2026-01-26T23:56:58.249+0900 [TRACE] vertex "output.result (expand)": dynamic subgraph completed successfully
2026-01-26T23:56:58.249+0900 [TRACE] vertex "output.result (expand)": visit complete
2026-01-26T23:56:58.249+0900 [TRACE] vertex "root": starting visit (*terraform.nodeCloseModule)
2026-01-26T23:56:58.249+0900 [TRACE] vertex "root": does not belong to any module instance
2026-01-26T23:56:58.249+0900 [TRACE] vertex "root": visit complete
2026-01-26T23:56:58.249+0900 [INFO]  backend/local: plan calling Plan
2026-01-26T23:56:58.249+0900 [DEBUG] Building and walking plan graph for NormalMode
2026-01-26T23:56:58.249+0900 [TRACE] building graph for walkPlan
2026-01-26T23:56:58.249+0900 [TRACE] Executing graph transform *terraform.ConfigTransformer
2026-01-26T23:56:58.249+0900 [TRACE] ConfigTransformer: Starting for path:
2026-01-26T23:56:58.250+0900 [TRACE] Executing graph transform *terraform.ActionTriggerConfigTransformer
2026-01-26T23:56:58.250+0900 [TRACE] Executing graph transform *terraform.ActionInvokePlanTransformer
2026-01-26T23:56:58.250+0900 [TRACE] Executing graph transform *terraform.RootVariableTransformer
2026-01-26T23:56:58.250+0900 [TRACE] Executing graph transform *terraform.ModuleVariableTransformer
2026-01-26T23:56:58.250+0900 [TRACE] Executing graph transform *terraform.variableValidationTransformer
2026-01-26T23:56:58.250+0900 [TRACE] variableValidationTransformer: adding validation nodes for any existing variable evaluation nodes
2026-01-26T23:56:58.250+0900 [TRACE] Executing graph transform *terraform.LocalTransformer
2026-01-26T23:56:58.250+0900 [TRACE] Executing graph transform *terraform.OutputTransformer
2026-01-26T23:56:58.250+0900 [TRACE] OutputTransformer: adding result as *terraform.nodeExpandOutput
2026-01-26T23:56:58.250+0900 [TRACE] Executing graph transform *terraform.checkTransformer
2026-01-26T23:56:58.250+0900 [TRACE] Executing graph transform *terraform.OrphanResourceInstanceTransformer
2026-01-26T23:56:58.250+0900 [TRACE] Executing graph transform *terraform.StateTransformer
2026-01-26T23:56:58.250+0900 [TRACE] StateTransformer: creating nodes for deposed instance objects only
2026-01-26T23:56:58.250+0900 [TRACE] Executing graph transform *terraform.AttachStateTransformer
2026-01-26T23:56:58.250+0900 [TRACE] Executing graph transform *terraform.OrphanOutputTransformer
2026-01-26T23:56:58.250+0900 [TRACE] Executing graph transform *terraform.AttachResourceConfigTransformer
2026-01-26T23:56:58.250+0900 [TRACE] Executing graph transform *terraform.graphTransformerMulti
2026-01-26T23:56:58.250+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.externalProviderTransformer
2026-01-26T23:56:58.250+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.externalProviderTransformer with new graph:
  local.empty_list (expand) - *terraform.nodeExpandLocal
  output.result (expand) - *terraform.nodeExpandOutput
  ------
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.ProviderConfigTransformer
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.ProviderConfigTransformer (no changes)
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.MissingProviderTransformer
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.MissingProviderTransformer (no changes)
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.ProviderTransformer
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.ProviderTransformer (no changes)
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.PruneProviderTransformer
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.PruneProviderTransformer (no changes)
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.RemovedModuleTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.AttachSchemaTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ModuleExpansionTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ExternalReferenceTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ReferenceTransformer
2026-01-26T23:56:58.251+0900 [DEBUG] ReferenceTransformer: "local.empty_list (expand)" references: []
2026-01-26T23:56:58.251+0900 [DEBUG] ReferenceTransformer: "output.result (expand)" references: []
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.AttachDependenciesTransformer
2026-01-26T23:56:58.251+0900 [TRACE] AttachDependenciesTransformer: output.result (expand) depends on []
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.attachDataResourceDependsOnTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.DestroyEdgeTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.pruneUnusedNodesTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.TargetsTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.QueryTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ForcedCBDTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ephemeralResourceCloseTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.CloseProviderTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.CloseRootModuleTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.TransitiveReductionTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Completed graph transform:
local.empty_list (expand) - *terraform.nodeExpandLocal
output.result (expand) - *terraform.nodeExpandOutput
root - *terraform.nodeCloseModule
  local.empty_list (expand) - *terraform.nodeExpandLocal
  output.result (expand) - *terraform.nodeExpandOutput
  ------
2026-01-26T23:56:58.251+0900 [DEBUG] Starting graph walk: walkPlan
2026-01-26T23:56:58.251+0900 [TRACE] vertex "local.empty_list (expand)": starting visit (*terraform.nodeExpandLocal)
2026-01-26T23:56:58.251+0900 [TRACE] vertex "local.empty_list (expand)": does not belong to any module instance
2026-01-26T23:56:58.251+0900 [TRACE] vertex "local.empty_list (expand)": expanding dynamic subgraph
2026-01-26T23:56:58.251+0900 [TRACE] Expanding local: adding local.empty_list as *terraform.NodeLocal
2026-01-26T23:56:58.251+0900 [TRACE] vertex "output.result (expand)": starting visit (*terraform.nodeExpandOutput)
2026-01-26T23:56:58.251+0900 [TRACE] vertex "output.result (expand)": does not belong to any module instance
2026-01-26T23:56:58.251+0900 [TRACE] vertex "output.result (expand)": expanding dynamic subgraph
2026-01-26T23:56:58.251+0900 [TRACE] Expanding output: adding output.result as *terraform.NodeApplyableOutput
2026-01-26T23:56:58.251+0900 [TRACE] vertex "local.empty_list (expand)": entering dynamic subgraph
2026-01-26T23:56:58.251+0900 [TRACE] vertex "output.result (expand)": entering dynamic subgraph
2026-01-26T23:56:58.251+0900 [TRACE] vertex "local.empty_list": starting visit (*terraform.NodeLocal)
2026-01-26T23:56:58.251+0900 [TRACE] vertex "local.empty_list": belongs to
2026-01-26T23:56:58.251+0900 [TRACE] vertex "output.result": starting visit (*terraform.NodeApplyableOutput)
2026-01-26T23:56:58.251+0900 [TRACE] vertex "output.result": belongs to
2026-01-26T23:56:58.251+0900 [TRACE] vertex "local.empty_list": visit complete
2026-01-26T23:56:58.251+0900 [TRACE] vertex "root": starting visit (terraform.graphNodeRoot)
2026-01-26T23:56:58.251+0900 [TRACE] vertex "root": does not belong to any module instance
2026-01-26T23:56:58.251+0900 [TRACE] vertex "root": visit complete
2026-01-26T23:56:58.251+0900 [TRACE] setValue: Saving Update change for output.result in changeset
2026-01-26T23:56:58.251+0900 [TRACE] vertex "local.empty_list (expand)": dynamic subgraph completed successfully
2026-01-26T23:56:58.251+0900 [TRACE] setValue: Saving value for output.result in state
2026-01-26T23:56:58.251+0900 [TRACE] setValue: Saving value for output.result in state
2026-01-26T23:56:58.251+0900 [TRACE] vertex "output.result": visit complete
2026-01-26T23:56:58.251+0900 [TRACE] vertex "local.empty_list (expand)": visit complete
2026-01-26T23:56:58.251+0900 [TRACE] vertex "root": starting visit (terraform.graphNodeRoot)
2026-01-26T23:56:58.251+0900 [TRACE] vertex "root": does not belong to any module instance
2026-01-26T23:56:58.251+0900 [TRACE] vertex "root": visit complete
2026-01-26T23:56:58.251+0900 [TRACE] vertex "output.result (expand)": dynamic subgraph completed successfully
2026-01-26T23:56:58.251+0900 [TRACE] vertex "output.result (expand)": visit complete
2026-01-26T23:56:58.251+0900 [TRACE] vertex "root": starting visit (*terraform.nodeCloseModule)
2026-01-26T23:56:58.251+0900 [TRACE] vertex "root": does not belong to any module instance
2026-01-26T23:56:58.251+0900 [TRACE] vertex "root": visit complete
2026-01-26T23:56:58.251+0900 [TRACE] Plan is complete
2026-01-26T23:56:58.251+0900 [TRACE] Plan is applyable
2026-01-26T23:56:58.251+0900 [DEBUG] building apply graph to check for errors
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ConfigTransformer
2026-01-26T23:56:58.251+0900 [TRACE] ConfigTransformer: Starting for path:
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.RootVariableTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ModuleVariableTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.variableValidationTransformer
2026-01-26T23:56:58.251+0900 [TRACE] variableValidationTransformer: adding validation nodes for any existing variable evaluation nodes
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.LocalTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.OutputTransformer
2026-01-26T23:56:58.251+0900 [TRACE] OutputTransformer: adding result as *terraform.nodeExpandOutput
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.DiffTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ActionTriggerConfigTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ActionInvokeApplyTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ActionDiffTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.DeferredTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.checkTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.AttachStateTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.OrphanOutputTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.AttachResourceConfigTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.graphTransformerMulti
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.externalProviderTransformer
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.externalProviderTransformer with new graph:
  local.empty_list (expand) - *terraform.nodeExpandLocal
  output.result (expand) - *terraform.nodeExpandOutput
  ------
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.ProviderConfigTransformer
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.ProviderConfigTransformer (no changes)
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.MissingProviderTransformer
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.MissingProviderTransformer (no changes)
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.ProviderTransformer
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.ProviderTransformer (no changes)
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Executing graph transform *terraform.PruneProviderTransformer
2026-01-26T23:56:58.251+0900 [TRACE] (graphTransformerMulti) Completed graph transform *terraform.PruneProviderTransformer (no changes)
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.RemovedModuleTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.AttachSchemaTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ModuleExpansionTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ExternalReferenceTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ReferenceTransformer
2026-01-26T23:56:58.251+0900 [DEBUG] ReferenceTransformer: "local.empty_list (expand)" references: []
2026-01-26T23:56:58.251+0900 [DEBUG] ReferenceTransformer: "output.result (expand)" references: []
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.AttachDependenciesTransformer
2026-01-26T23:56:58.251+0900 [TRACE] AttachDependenciesTransformer: output.result (expand) depends on []
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.checkStartTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ForcedCBDTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.DestroyEdgeTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.CBDEdgeTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.pruneUnusedNodesTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.TargetsTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.ephemeralResourceCloseTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.CloseProviderTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.CloseRootModuleTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Executing graph transform *terraform.TransitiveReductionTransformer
2026-01-26T23:56:58.251+0900 [TRACE] Completed graph transform:
local.empty_list (expand) - *terraform.nodeExpandLocal
output.result (expand) - *terraform.nodeExpandOutput
root - *terraform.nodeCloseModule
  local.empty_list (expand) - *terraform.nodeExpandLocal
  output.result (expand) - *terraform.nodeExpandOutput
  ------
2026-01-26T23:56:58.251+0900 [INFO]  backend/local: plan operation completed

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
2026-01-26T23:56:58.251+0900 [TRACE] statemgr.Filesystem: removing lock metadata file .terraform.tfstate.lock.info
2026-01-26T23:56:58.251+0900 [TRACE] statemgr.Filesystem: unlocking terraform.tfstate using fcntl flock

Expected Behavior

When the displayed output shows "No changes. Your infrastructure matches the configuration.", terraform plan -detailed-exitcode should return exit code 0.

Actual Behavior

The CLI displays "No changes. Your infrastructure matches the configuration." but returns exit code 2, indicating changes are present.

$ terraform plan -detailed-exitcode

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.

$ echo $?
2

Steps to Reproduce

#!/bin/bash
mkdir -p /tmp/tf-repro && cd /tmp/tf-repro

# Step 1: Create initial config with conditional expression
cat > main.tf << 'EOF'
locals {
    empty_list = tolist([])
}

output "result" {
    value = {
        items = length(local.empty_list) > 0 ? local.empty_list : [""]
    }
}
EOF

# Step 2: Initialize and apply
terraform init
terraform apply -auto-approve

# Step 3: Modify output to hardcoded value (same result, different expression)
cat > main.tf << 'EOF'
output "result" {
    value = {
        items = [""]
    }
}
EOF

# Step 4: Run plan with detailed-exitcode
terraform plan -detailed-exitcode
echo "Exit code: $?"
# Expected: 0, Actual: 2

Additional Context

Investigation suggests this is caused by two different comparison mechanisms:

  1. Display logic (internal/command/jsonformat/jsondiff/diff.go:95): Uses reflect.DeepEqual on JSON-serialized data
  2. Exit code logic (internal/terraform/node_output.go:727-734): Uses cty.Value.Equals() with strict type checking

The conditional expression length(...) > 0 ? list : [""] produces a list(string) type (due to type unification), while the hardcoded [""] produces a tuple([string]) type. The values are identical, but the types
differ.

  • reflect.DeepEqual (JSON) → true → "No changes" displayed
  • cty.Value.Equals() (cty) → false → Action = Update → exit code 2

Workaround: Explicitly convert the type:

output "result" {
    value = {
        items = tolist([""])
    }
}

References

Generative AI / LLM assisted development?

Claude Code was used for:

  • Navigating Terraform source code to identify the root cause
  • Tracing the code paths for exit code determination vs. display logic

All analysis results were independently verified by the reporter through:

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugnewnew issue not yet triaged

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions