Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/v1.15/BUG FIXES-20260305-120000.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: BUG FIXES
body: 'configs: fix nil pointer panic when a moved block has invalid addresses (e.g. quoted strings)'
time: 2026-03-05T12:00:00.000000+00:00
custom:
Issue: "34041"
10 changes: 10 additions & 0 deletions internal/configs/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,16 @@ func TestModule_required_providers_multiple(t *testing.T) {
}
}

// Moved blocks with invalid (e.g. quoted) addresses combined with import
// blocks should produce errors but must not panic.
// https://github.com/hashicorp/terraform/issues/34041
func TestModule_moved_with_invalid_addresses_no_panic(t *testing.T) {
_, diags := testModuleFromDir("testdata/invalid-modules/moved-with-invalid-addresses")
if !diags.HasErrors() {
t.Fatal("module should have error diags, but does not")
}
}

// A module may have required_providers configured in files loaded later than
// resources. These provider settings should still be reflected in the
// resources' configuration.
Expand Down
24 changes: 13 additions & 11 deletions internal/configs/moved.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,20 @@ func decodeMovedBlock(block *hcl.Block) (*Moved, hcl.Diagnostics) {
}
}

if diags.HasErrors() {
return nil, diags
}

// we can only move from a module to a module, resource to resource, etc.
if !diags.HasErrors() {
if !moved.From.MightUnifyWith(moved.To) {
// We can catch some obviously-wrong combinations early here,
// but we still have other dynamic validation to do at runtime.
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid \"moved\" addresses",
Detail: "The \"from\" and \"to\" addresses must either both refer to resources or both refer to modules.",
Subject: &moved.DeclRange,
})
}
if !moved.From.MightUnifyWith(moved.To) {
// We can catch some obviously-wrong combinations early here,
// but we still have other dynamic validation to do at runtime.
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid \"moved\" addresses",
Detail: "The \"from\" and \"to\" addresses must either both refer to resources or both refer to modules.",
Subject: &moved.DeclRange,
})
}

return moved, diags
Expand Down
5 changes: 1 addition & 4 deletions internal/configs/moved_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,7 @@ func TestMovedBlock_decode(t *testing.T) {
}),
DefRange: blockRange,
},
&Moved{
From: mustMoveEndpointFromExpr(foo_expr),
DeclRange: blockRange,
},
nil,
"Missing required argument",
},
"error: type mismatch": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Quoted addresses (issue #34041)
moved {
from = "module.foo"
to = "module.bar"
}

# Unqualified resource names without type prefix (issue #34162)
moved {
from = bar
to = foo
}

import {
to = test_instance.foo
id = "test"
}
5 changes: 5 additions & 0 deletions internal/refactoring/move_statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ func FindMoveStatements(rootCfg *configs.Config) []MoveStatement {
func findMoveStatements(cfg *configs.Config, into []MoveStatement) []MoveStatement {
modAddr := cfg.Path
for _, mc := range cfg.Module.Moved {
if mc.From == nil || mc.To == nil {
// Invalid addresses should've been caught during original
// configuration decoding, in the configs package.
continue
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unclear if this is the correct thing to do, versus surface some sort of error. (Relaying a comment from the triage meeting.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point — I've removed this guard. The primary fix in decodeMovedBlock returns nil early when diagnostics contain errors, so nil From/To should never reach this code path. I've posted a detailed explanation of the approach on #34041 for discussion.

}
fromAddr, toAddr := addrs.UnifyMoveEndpoints(modAddr, mc.From, mc.To)
if fromAddr == nil || toAddr == nil {
// Invalid combination should've been caught during original
Expand Down