Skip to content

genconfig: handle null nested attribute values without panic#38604

Open
net0pyr wants to merge 2 commits into
hashicorp:mainfrom
net0pyr:fix/38569-null-nested-attr
Open

genconfig: handle null nested attribute values without panic#38604
net0pyr wants to merge 2 commits into
hashicorp:mainfrom
net0pyr:fix/38569-null-nested-attr

Conversation

@net0pyr
Copy link
Copy Markdown

@net0pyr net0pyr commented May 16, 2026

Fixes #38569

Target Release

1.16.x

Rollback Plan

  • If a change needs to be reverted, we will roll out an update to the code within 7 days.

Changes to Security Controls

None.

CHANGELOG entry

  • This change is user-facing and I added a changelog entry.

Root cause

cty.Value.GetAttr asserts the value's internal representation to map[string]interface{}; that assertion panics on cty.NullVal(...) because the representation is nil. Two functions in internal/genconfig/generate_config.gowriteConfigNestedTypeAttributeFromExisting and writeConfigBlocksFromExisting — called GetAttr on the incoming parent value without first checking IsNull(). In the terraform query -generate-config-out flow, generateHCLListResourceDef (in internal/terraform) deliberately hands genconfig cty.NullVal(schema.Body.ImpliedType()) whenever the provider returned no state for a queried resource, which made the panic reachable from real usage.

Fix

Add an IsNull() guard before each problematic GetAttr call. In writeConfigNestedTypeAttributeFromExisting the guard emits a literal null for the attribute when the parent is null, mirroring the existing handling for null primitives in writeConfigAttributesFromExisting (which falls back to attrS.EmptyValue() for the same situation) and the per-nesting nestedVal.IsNull() branches further down in the same function. In writeConfigBlocksFromExisting the guard short-circuits the iteration because writeConfigNestedBlockFromExisting already treats a null block value as "nothing to emit". The diff stays inside internal/genconfig.

Regression test

Adds two table-driven cases to TestConfigGeneration in internal/genconfig/generate_config_test.go:

  • resource_with_null_state constructs cty.NullVal(...) as the resource state and exercises every nested-type nesting mode (single/list/map) plus a nested block, asserting that generation completes without panic and emits well-formed HCL.
  • resource_with_nested_value_sibling covers the inverse: a non-null parent with real nested values, to guard against the new null guard becoming too eager and silently dropping data.

Both tests construct the cty.Value directly — no provider, no network, no CLI invocation.

No public API changes

The change is internal to internal/genconfig. No exported symbols, function signatures, or behaviours for non-null inputs are altered.

AI Usage

This PR was developed with assistance from Claude (Anthropic) as a coding assistant. Specific role: I used Claude to help locate the panic site.

@net0pyr net0pyr requested a review from a team as a code owner May 16, 2026 12:44
@hashicorp-cla-app
Copy link
Copy Markdown

hashicorp-cla-app Bot commented May 16, 2026

CLA assistant check
All committers have signed the CLA.

@hashicorp-cla-app
Copy link
Copy Markdown

CLA assistant check

Thank you for your submission! We require that all contributors sign our Contributor License Agreement ("CLA") before we can accept the contribution. Read and sign the agreement

Learn more about why HashiCorp requires a CLA and what the CLA includes

Have you signed the CLA already but the status is still pending? Recheck it.

Comment thread internal/genconfig/generate_config.go Outdated
// A null parent value here means the surrounding object has no value
// for this nested attribute (e.g. the entire resource state passed in
// from a list resource was cty.NullVal, or a null element was emitted
// inside a nested list/map). Treat it like a null nested value and
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

A null resource value means the resource instance does not exist, so it should not be returned from a list resource. You can't generate config for a null resource value, because it is not there to be confnigured.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Moved the fix into generateHCLListResourceDef. The null parent that was reaching writeConfigNestedTypeAttributeFromExisting came from the explicit cty.NullVal(schema.Body.ImpliedType()) fallback there. Replaced it with schema.Body.EmptyValue() (and added a IsNull() check on the provider-supplied state attribute as well), so genconfig never sees a fully-null parent value.

})),
expected: `
resource "tfcoremock_simple_resource" "empty" {
list = null
Copy link
Copy Markdown
Member

@jbardin jbardin May 18, 2026

Choose a reason for hiding this comment

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

This looks like you're testing for null attributes, but the linked issue is about a null nested block for timeouts.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Replaced the two NestedType-attribute test cases with a single resource_with_empty_state case that mirrors the shape the caller now produces: a non-null object with null primitive attributes, null nested-type attributes (single/list/map) and a null nested block. That covers both the panic regression and the legacy-block timeouts shape you flagged, without claiming to fix a non-issue in genconfig itself.

@crw
Copy link
Copy Markdown
Contributor

crw commented May 18, 2026

@net0pyr please also disclose your use of GenAI tooling per our Contributing.md guidelines. Thanks!

@net0pyr net0pyr requested a review from jbardin May 19, 2026 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

terraform query -generate-config-out crashes when the target resource has a null timeouts attribute.

3 participants