Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes crossplane-contrib/provider-upjet-aws#1579.
Cause
The panic originates from:
https://github.com/hashicorp/terraform-provider-aws/blob/v5.78.0/internal/service/ec2/ec2_instance.go#L2385
The code checks for existence of
root_block_device
, usingd.GetOk("root_block_device")
, before accessing its tagsroot_block_device[0].tags
. The problem stems from the fact that Terraform has multiple sources of resource data which are combined as needed. These sources are: state, config, diff, set. When a piece of data exists in multiple sources, the one that comes later in the list is used.Theoretically,
d.GetOk()
andtags.ResolveDuplicates()
may read from different sources, which may cause different kinds of errors. In our case though, both read fromstate
. Unfortunately, even the sources have “subsources”, from which a data can be read. Forstate
, these “subsources” are Attributes, RawConfig, RawState, RawPlanWhereas
d.GetOk()
uses the multilevel reader that reads fromAttributes
,tags.ResolveDuplicates()
reads fromRawConfig
.To summarize,
d.GetOk("root_block_device")
returnsd.state.Attributes["root_block_device"]
, which exists. Then,tags.ResolveDuplicates()
accessesd.state.RawConfig.v["root_block_device"]
, which is nil.Fix
The panic occurs at
cty.LengthInt()
, which is called from GetAnyAttr(). Note that,LengthInt()
is called only for list or tuple types. Nil tuples don't panic inLengthInt()
. So, to prevent the panic, we only check whether the value is a non-nil and known list before callingLengthInt()
.