diff --git a/.changelog/118.txt b/.changelog/118.txt new file mode 100644 index 000000000..b2c70c61d --- /dev/null +++ b/.changelog/118.txt @@ -0,0 +1,3 @@ +```release-note:bug +tfsdk: Don't attempt validation on the nested attributes of a null or unknown `SingleNestedAttribute` +``` \ No newline at end of file diff --git a/tfsdk/attribute.go b/tfsdk/attribute.go index d1d39c4f4..55c1770c4 100644 --- a/tfsdk/attribute.go +++ b/tfsdk/attribute.go @@ -341,18 +341,33 @@ func (a Attribute) validate(ctx context.Context, req ValidateAttributeRequest, r } } case NestingModeSingle: - for nestedName, nestedAttr := range a.Attributes.GetAttributes() { - nestedAttrReq := ValidateAttributeRequest{ - AttributePath: req.AttributePath.WithAttributeName(nestedName), - Config: req.Config, - } - nestedAttrResp := &ValidateAttributeResponse{ - Diagnostics: resp.Diagnostics, - } + o, ok := req.AttributeConfig.(types.Object) + + if !ok { + err := fmt.Errorf("unknown attribute value type (%T) for nesting mode (%T) at path: %s", req.AttributeConfig, nm, req.AttributePath) + resp.Diagnostics.AddAttributeError( + req.AttributePath, + "Attribute Validation Error", + "Attribute validation cannot walk schema. Report this to the provider developer:\n\n"+err.Error(), + ) + + return + } + + if !o.Null && !o.Unknown { + for nestedName, nestedAttr := range a.Attributes.GetAttributes() { + nestedAttrReq := ValidateAttributeRequest{ + AttributePath: req.AttributePath.WithAttributeName(nestedName), + Config: req.Config, + } + nestedAttrResp := &ValidateAttributeResponse{ + Diagnostics: resp.Diagnostics, + } - nestedAttr.validate(ctx, nestedAttrReq, nestedAttrResp) + nestedAttr.validate(ctx, nestedAttrReq, nestedAttrResp) - resp.Diagnostics = nestedAttrResp.Diagnostics + resp.Diagnostics = nestedAttrResp.Diagnostics + } } default: err := fmt.Errorf("unknown attribute validation nesting mode (%T: %v) at path: %s", nm, nm, req.AttributePath)