{"record":{"id":"d20b6bdd7a79f30d","repo":"hashicorp/terraform","slug":"s-s-nestingset-attributes-may-not-contain-attrib","errorCode":null,"errorMessage":"%s%s: NestingSet attributes may not contain attributes of cty.DynamicPseudoType","messagePattern":"(.+?)(.+?): NestingSet attributes may not contain attributes of cty\\.DynamicPseudoType","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configs/configschema/internal_validate.go","lineNumber":180,"sourceCode":"\n\tif a.Type != cty.NilType {\n\t\tif a.NestedType != nil {\n\t\t\terr = errors.Join(fmt.Errorf(\"%s: Type and NestedType cannot both be set\", name))\n\t\t}\n\t}\n\n\tif a.NestedType != nil {\n\t\tswitch a.NestedType.Nesting {\n\t\tcase NestingSingle, NestingMap, NestingGroup:\n\t\t\t// no validations to perform\n\t\tcase NestingList, NestingSet:\n\t\t\tif a.NestedType.Nesting == NestingSet {\n\t\t\t\tety := a.ImpliedType()\n\t\t\t\tif ety.HasDynamicTypes() {\n\t\t\t\t\t// This is not permitted because the HCL (cty) set implementation\n\t\t\t\t\t// needs to know the exact type of set elements in order to\n\t\t\t\t\t// properly hash them, and so can't support mixed types.\n\t\t\t\t\terr = errors.Join(err, fmt.Errorf(\"%s%s: NestingSet attributes may not contain attributes of cty.DynamicPseudoType\", prefix, name))\n\t\t\t\t}\n\t\t\t\tif a.NestedType.ContainsWriteOnly() {\n\t\t\t\t\t// This is not permitted because any marks within sets will\n\t\t\t\t\t// be hoisted up the outer set value, so only the set itself\n\t\t\t\t\t// can be WriteOnly.\n\t\t\t\t\terr = errors.Join(err, fmt.Errorf(\"%s%s: NestingSet attributes may not contain WriteOnly attributes\", prefix, name))\n\t\t\t\t}\n\t\t\t}\n\t\tdefault:\n\t\t\terr = errors.Join(err, fmt.Errorf(\"%s%s: invalid nesting mode %s\", prefix, name, a.NestedType.Nesting))\n\t\t}\n\t\tfor name, attrS := range a.NestedType.Attributes {\n\t\t\tif attrS == nil {\n\t\t\t\terr = errors.Join(err, fmt.Errorf(\"%s%s: attribute schema is nil\", prefix, name))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\terr = errors.Join(err, attrS.internalValidate(name, prefix))\n\t\t}","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/configs/configschema/internal_validate.go#L162-L198","documentation":"Thrown during schema validation when a NestingSet block's implied cty type contains DynamicPseudoType. HCL's set implementation must hash each element deterministically, which requires a fully-known element type; dynamic (union) element types cannot be hashed uniquely, so the configuration is rejected at validation time rather than producing silently wrong set semantics later.","triggerScenarios":"Defining a NestedType with Nesting: NestingSet where at least one nested attribute uses cty.DynamicPseudoType (or is omitted/optional in a way that yields a dynamic type), then invoking InternalValidate. Common when porting a list-of-dicts schema to a set and one attribute is left as a generic any/dynamic type.","commonSituations":"Provider schemas that accept arbitrary key/value metadata inside a set; mixing SDK v1 'Type' fields that map to cty.DynamicPseudoType inside a set block; upgrading a provider where a previously List-typed block is changed to Set without auditing dynamic-typed members.","solutions":["Replace every cty.DynamicPseudoType attribute inside the NestingSet block with a concrete type (string, number, bool, object, etc.).","If the values are genuinely heterogeneous, switch the nesting mode from NestingSet to NestingList (lists do not hash elements and tolerate dynamic types).","If a JSON-blob-style field is needed, encode it as a single string-typed attribute (e.g. JSON-encoded) rather than a dynamic-typed one.","Run InternalValidate() in provider unit tests to surface this at test time."],"exampleFix":"// before\nNestedType: &configschema.Object{\n    Nesting: configschema.NestingSet,\n    Attributes: map[string]*configschema.Attribute{\n        \"value\": {Type: cty.DynamicPseudoType, Optional: true},\n    },\n}\n\n// after — concrete type, or move to NestingList\nNestedType: &configschema.Object{\n    Nesting: configschema.NestingSet,\n    Attributes: map[string]*configschema.Attribute{\n        \"value\": {Type: cty.String, Optional: true},\n    },\n}","handlingStrategy":"validation","validationCode":"func assertSetHasNoDynamic(o *configschema.Object) error {\n    if o == nil || o.Nesting != configschema.NestingSet {\n        return nil\n    }\n    for name, a := range o.Attributes {\n        if a == nil { continue }\n        if a.Type == cty.DynamicPseudoType {\n            return fmt.Errorf(\"NestingSet attribute %q uses cty.DynamicPseudoType\", name)\n        }\n        if err := assertSetHasNoDynamic(a.NestedType); err != nil { return err }\n    }\n    return nil\n}","typeGuard":"func canHashElementType(o *configschema.Object) bool {\n    if o == nil || o.Nesting != configschema.NestingSet { return true }\n    ety := o.ImpliedType()\n    return !ety.HasDynamicTypes()\n}","tryCatchPattern":null,"preventionTips":["Avoid cty.DynamicPseudoType inside any NestingSet block; prefer concrete types.","If heterogeneous values are unavoidable, switch to NestingList.","Encode unstructured payloads as a JSON string attribute rather than a dynamic type."],"tags":["schema-validation","configschema","nesting-set","cty","go"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}