Plan failures with terraform 1.5.0 and framework 1.2.0

Terraform 1.4.6 works with my provider, but 1.5.0 does not.

The error is:

│ Error: Provider produced invalid plan
│ 
│ Provider "registry.terraform.io/juniper/apstra" planned an invalid value for apstra_interface_map.test.interfaces: count in plan
│ (cty.UnknownVal(cty.Number)) disagrees with count in config (cty.NumberIntVal(2)).
│ 
│ This is a bug in the provider, which should be reported in the provider's own issue tracker.

The attribute in question is a Required SetNestedAttribute with an Optional + Computed attribute inside.

Changing the nested Optional + Computed attribute to Required clears things up.

I’ve had problems in other cases with complicated SetNestedAttributes, but those tended to revolve around dereferencing set elements with unknown nested element values. Failing to count the set members (I guess that’s what’s happening?) seems new.

Is this expected behavior?

Thanks!

Hey @hQnVyLRx :wave: Thanks for raising this and sorry you’re running into trouble here. Let’s see if we can figure out what’s going on.

Do you happen to have the associated configuration snippet for this handy? It’d also be helpful to know if the configuration was changed to trigger a create/update plan or if this only happening during a plan that’s expected to cause no changes.

One additional, but potentially odd, troubleshooting step here might be to see what happens by just removing the UseStateForUnknown plan modifier since its under a set element: Unexpected Behavior With Plan Modifier (UseStateForUnknown) Prior State Under Lists and Sets · Issue #709 · hashicorp/terraform-plugin-framework · GitHub

The error diagnostic content/formatting seems to suggest the error is being raised by Terraform core though. That doesn’t always mean it wasn’t because of something on the provider side, but seeing the behavior change only through upgrading the Terraform version seems most suspect. I’m guessing though that maybe there could have been subtle internal changes to the core planning logic between 1.4 and 1.5 since the newer version implemented import logic into the plan graph. I believe 1.5 also introduced some subtle internal type system updates. It may be worth raising an issue in Issues · hashicorp/terraform · GitHub in case one of those maintainers may recognize a recent change that would have potentially caused this.

Thank you @bflad,

The error occurs on initial plan generation. No need for any prior state.

You can replicate the behavior with (a) the following config and (b) an immediate return in the provider’s Configure() and the resource’s ValidateConfig() from the provider’s main branch. Without those returns, the provider will bail out too early.

The config required is:

# The bogus URL below only "works" if the following functions are modified to return immediately:
# - Configure() in apstra/Provider.go()
# - ValidateConfig() in apstra/resource_interface_map.go()
provider "apstra" { url = "https://user:pass@0.0.0.0" }

resource "apstra_interface_map" "x" {
  name              = "x"
  logical_device_id = "x"
  device_profile_id = "x"
  interfaces = [
    { logical_device_port = "1/1", physical_interface_name = "x" },
    { logical_device_port = "1/2", physical_interface_name = "y" },
  ]
}

I noticed this morning that the error doesn’t occur when only a single interface is supplied in the configuration.

Removing UseStateForUnknown in the nested attribute (two instances of it) doesn’t seem to have made any difference in the few minutes I’ve had to look at it this morning.

I’ll check out #709.

I think the problem here is that interfaces is a nested set, but you have an optionally-computed attribute inside that set. Because elements of a set are determined by their entire value, ~if any attribute becomes unknown the entire set therefor becomes unknown~ (EDIT: turns out the framework is not causing this to happen), which is not allowed if there is configuration present for that set.

It basically comes down to optional+computed attributes are not really possible within a set.

Hi @jbardin,

Thank you for your reply.

Does this problem apply only to “optional+computed” attributes, or also to nested set attributes which are merely “computed”?

It seems like they’d be equally “unknown” during plan generation.

If there’s specific guidance about the rules for various nesting scenarios, I’d appreciate a pointer to where I can learn more.

Also, I’m struggling to square “not really possible” with “worked in terraform 1.4.6” and “works fine with 1 set element, but not with 2 set elements”

Oh yes, it’s really just the computed concept that is a problem here (because really from a plan validation perspective, something is either computed, or it isn’t, the optional aspect is irrelevant). The legacy SDK tried to work around these partial-value-in-set problems with the idea of the custom set hash function, but that doesn’t work because what is treated as a set element must align exactly with how core treats the set.

I’m not certain how this worked for you in v1.4, because the point where this is erroring would have been a crash in prior versions since we never could encounter the situation with the old SDK. With a single element, the set might not be entirely unknown (I can’t recall how precise that evaluation is), since there is no possibility of multiple elements resolving to the same value.

Now that I think about it some more though, perhaps we could make this pass now that we have the more refined structural attribute handling … I need to look into it a little more closely, but it’s possible this validation check could be made to pass with better validation after apply.

I think I understand the general problem of dereferencing set elements (by value) and how that falls apart when (part of) the value is unknown.

I’ve stumbled across it before and (somewhat awkwardly) forced things into maps instead.

The error text sounds to me like it’s a failure to count the set elements, which is harder for me to understand.

I’m whipping up a skeleton provider for easier diagnosis.

A skeleton provider based on framework 1.3.1 lives here.

Just to follow up here, It turns out the provider is not returning an unknown set value like I assumed, the plan from the provider looks fine.

The bug was introduced via a go-cty quirk which interprets the set length differently depending on the method used (issue here).

1 Like

The fix for this has been released today with Terraform 1.5.1.

1 Like