{"record":{"id":"76dd6b11beb13f5a","repo":"hashicorp/terraform","slug":"s-s-block-schema-is-nil","errorCode":null,"errorMessage":"%s%s: block schema is nil","messagePattern":"(.+?)(.+?): block schema is nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configs/configschema/internal_validate.go","lineNumber":51,"sourceCode":"\t\tmultiErr = errors.Join(multiErr, fmt.Errorf(\"top-level block: DeprecationMessage must not be set when Deprecated is false\"))\n\t}\n\n\tfor name, attrS := range b.Attributes {\n\t\tif attrS == nil {\n\t\t\tmultiErr = errors.Join(multiErr, fmt.Errorf(\"%s%s: attribute schema is nil\", prefix, name))\n\t\t\tcontinue\n\t\t}\n\t\tmultiErr = errors.Join(multiErr, attrS.internalValidate(name, prefix))\n\n\t\t// all attributes within a computed block must also be computed\n\t\tif b.Computed && !attrS.Computed {\n\t\t\tmultiErr = errors.Join(multiErr, fmt.Errorf(\"%s%s: all attributes within computed blocks must also be computed\", prefix, name))\n\t\t}\n\t}\n\n\tfor name, blockS := range b.BlockTypes {\n\t\tif blockS == nil {\n\t\t\tmultiErr = errors.Join(multiErr, fmt.Errorf(\"%s%s: block schema is nil\", prefix, name))\n\t\t\tcontinue\n\t\t}\n\n\t\tif _, isAttr := b.Attributes[name]; isAttr {\n\t\t\tmultiErr = errors.Join(multiErr, fmt.Errorf(\"%s%s: name defined as both attribute and child block type\", prefix, name))\n\t\t} else if !validName.MatchString(name) {\n\t\t\tmultiErr = errors.Join(multiErr, fmt.Errorf(\"%s%s: name may contain only lowercase letters, digits and underscores\", prefix, name))\n\t\t}\n\t\tif !blockS.Deprecated && blockS.DeprecationMessage != \"\" {\n\t\t\tmultiErr = errors.Join(multiErr, fmt.Errorf(\"%s%s: DeprecationMessage must not be set when Deprecated is false\", prefix, name))\n\t\t}\n\n\t\tif blockS.MinItems < 0 || blockS.MaxItems < 0 {\n\t\t\tmultiErr = errors.Join(multiErr, fmt.Errorf(\"%s%s: MinItems and MaxItems must both be greater than zero\", prefix, name))\n\t\t}\n\n\t\t// any nested blocks within a computed block must also be computed\n\t\tif b.Computed && !blockS.Computed {","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/configs/configschema/internal_validate.go#L33-L69","documentation":"During schema validation, an entry in the Block's BlockTypes map (nested block types) has a nil value. Every nested block type name must map to a non-nil *NestedBlock schema. This is analogous to the nil-attribute error but for nested block definitions — a developer registered a block type name but never populated its schema.","triggerScenarios":"Block.BlockTypes map contains a key mapped to nil. Triggered when schema construction code adds a nested block type key without a corresponding *NestedBlock value — e.g., dynamic map population that leaves gaps, or a schema generator bug.","commonSituations":"Provider developer builds BlockTypes map conditionally and some paths leave nil entries. Schema code generation tool emits incomplete maps. Refactoring removed a NestedBlock definition but left the map key. Dynamic schema construction loops that skip certain entries.","solutions":["Audit the provider schema construction for the resource/data source in the error message.","Ensure every key in BlockTypes maps to a fully populated *configschema.NestedBlock.","Use conditional logic to omit keys entirely rather than setting nil values.","Add unit tests that call InternalValidate() on every resource and data source schema."],"exampleFix":"// before — nil nested block\nBlockTypes: map[string]*NestedBlock{\n    \"config\":   {Nesting: ListNesting, Block: Block{...}},\n    \"settings\": nil,  // ← bug\n}\n\n// after — populate or omit\nBlockTypes: map[string]*NestedBlock{\n    \"config\":   {Nesting: ListNesting, Block: Block{...}},\n    \"settings\": {Nesting: SetNesting, Block: Block{...}},\n}","handlingStrategy":"validation","validationCode":"// Provider developers: ensure no nil nested block values\nfunc sanitizeBlockTypeMap(blocks map[string]*configschema.NestedBlock) map[string]*configschema.NestedBlock {\n    clean := make(map[string]*configschema.NestedBlock, len(blocks))\n    for k, v := range blocks {\n        if v == nil {\n            log.Printf(\"WARN: block type %q has nil schema, removing\", k)\n            continue\n        }\n        clean[k] = v\n    }\n    return clean\n}\n\n// Unit test gate:\nfunc TestNoNilBlockTypes(t *testing.T) {\n    if err := myResourceSchema().InternalValidate(); err != nil {\n        t.Fatal(err)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never add a key to BlockTypes without a fully populated *NestedBlock value.","Use conditional omission rather than nil assignment.","Gate every schema change behind an InternalValidate() unit test."],"tags":["schema","validation","provider-development","nil-pointer","nested-blocks","internal"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}