Recurring Change observed in terraform plan for dynamic blocks

Hello

we’re building a new terraform custom provider and are facing a use case as follows:

The schema provisions a dynamic block as below. During resource creation, we’re able to send the information to the backend. However, when the same is being saved onto the state, we observe the data is being compared among the other block object. Eg: Field_A.Name is compared with Field_B.Name and vice-versa… and a recurring change/error is shown with-in the provider.

"configuration": schema.SingleNestedBlock{
	"Blocks" : map[string]schema.Block{
		"tables": schema.ListNestedBlock{
					NestedObject: schema.NestedBlockObject{
						Blocks: map[string]schema.Block{
							"rows": schema.ListNestedBlock{
										NestedObject: schema.NestedBlockObject{
											Blocks: map[string]schema.Block{
												"fields": schema.ListNestedBlock{
															NestedObject: schema.NestedBlockObject{
																Attributes: map[string]schema.Attribute{
																	"name": schema.StringAttribute{
																				Required:    true,
																			},
																	"value": schema.StringAttribute{
																			Optional:    true,
																	},
																}
															}
													}
											}
										}
									}
						}
					}
				}
			}
	}

and the input from tf resource would be:

configuration {
	tables {
		name = "1_FIRST_TABLE"
		rows {
			fields {
				name      = "1_FIRST_KEY"
				value     = "FIRST_VALUE"
			}
			fields {
				name      = "2_SECOND_KEY"
				value     = "SECOND_VALUE"
			}
			default_row = false
		}
	}

    tables {
      name      = "2_SECOND_TABLE"
    }
}

We’ve tried a workaround by sorting these Fields before sending them into the state and after retrieving them from the state. However, none of these seem to put a fix for this.

I’d be glad if you could please help us with guidance on how to handle this use case.

Hi @Vasista-Eranki :wave: Welcome to HashiCorp Discuss and thank you for taking the time to post on here.

To help understand your situation better, it would be great if you could show the Terraform plan output and/or errors. In general though, if the backend API treats the data as unordered, then it should be modeled in the Terraform Provider as a set type (unordered collection) rather than a list type (ordered collection).

Also to just to clarify, when you mention “The schema provisions a dynamic block”, you are not trying to refer to the Terraform configuration language dynamic block functionality, correct? It is unlikely, but there have been edge cases in the past where Terraform’s planning process/output can get confused while handling that particular language feature. Your configuration example is not showing that, but just trying to ensure that is also not at play in this situation.

Hello @bflad

Good day.

Thanks for the response.

Here is the outcome after the apply:

│ Error: Provider produced inconsistent result after apply
│
│ When applying changes to 
*****RESOURCE******.********NAME********, provider "provider[\"app.terraform.io/**********/***********\"]" produced an unexpected new value:
│ .configuration.tables[0].rows[0].fields[0].name: was cty.StringVal("1_FIRST_KEY"), but now cty.StringVal("2_SECOND_KEY").
│
│ This is a bug in the provider, which should be reported in the provider's own issue tracker.
╵
╷
│ Error: Provider produced inconsistent result after apply
│
│ When applying changes to 
*****RESOURCE******.********NAME********, provider "provider[\"app.terraform.io/**********/***********\"]" produced an unexpected new value:
│ .configuration.tables[0].rows[0].fields[0].value: was cty.StringVal("FIRST_VALUE"), but now cty.StringVal("SECOND_VALUE").
│
│ This is a bug in the provider, which should be reported in the provider's own issue tracker.
╵
╷
│ Error: Provider produced inconsistent result after apply
│
│ When applying changes to 
*****RESOURCE******.********NAME********, provider "provider[\"app.terraform.io/**********/***********\"]" produced an unexpected new value:
│ .configuration.tables[0].rows[0].fields[1].name: was cty.StringVal("2_SECOND_KEY"), but now cty.StringVal("1_FIRST_KEY").
│
│ This is a bug in the provider, which should be reported in the provider's own issue tracker.
╵
╷
│ Error: Provider produced inconsistent result after apply
│
│ When applying changes to 
*****RESOURCE******.********NAME********, provider "provider[\"app.terraform.io/**********/***********\"]" produced an unexpected new value:
│ .configuration.tables[0].rows[0].fields[1].value: was cty.StringVal("SECOND_VALUE"), but now cty.StringVal("FIRST_VALUE").
│
│ This is a bug in the provider, which should be reported in the provider's own issue tracker.
╵

Hi @Vasista-Eranki,

The error output looks like what @bflad was referring to, the provider returned the values in a different order from the configuration. Because a list is an ordered data structure, the order must be maintained by the provider. If the API returns the values unordered, you can use a set for the block type.

Thanks, @bflad & @jbardin.

The change suggested by @bflad has worked for us.