hashicorp/terraform · error

: block schema is nil

Error message

%s%s: block schema is nil

What it means

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.

Solutions

  1. Audit the provider schema construction for the resource/data source in the error message.
  2. Ensure every key in BlockTypes maps to a fully populated *configschema.NestedBlock.
  3. Use conditional logic to omit keys entirely rather than setting nil values.
  4. Add unit tests that call InternalValidate() on every resource and data source schema.

Example fix

// before — nil nested block
BlockTypes: map[string]*NestedBlock{
    "config":   {Nesting: ListNesting, Block: Block{...}},
    "settings": nil,  // ← bug
}

// after — populate or omit
BlockTypes: map[string]*NestedBlock{
    "config":   {Nesting: ListNesting, Block: Block{...}},
    "settings": {Nesting: SetNesting, Block: Block{...}},
}
Defensive patterns

Strategy: validation

Validate before calling

// Provider developers: ensure no nil nested block values
func sanitizeBlockTypeMap(blocks map[string]*configschema.NestedBlock) map[string]*configschema.NestedBlock {
    clean := make(map[string]*configschema.NestedBlock, len(blocks))
    for k, v := range blocks {
        if v == nil {
            log.Printf("WARN: block type %q has nil schema, removing", k)
            continue
        }
        clean[k] = v
    }
    return clean
}

// Unit test gate:
func TestNoNilBlockTypes(t *testing.T) {
    if err := myResourceSchema().InternalValidate(); err != nil {
        t.Fatal(err)
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/76dd6b11beb13f5a. Report an issue: GitHub.

Appendix: source

Thrown at internal/configs/configschema/internal_validate.go:51

		multiErr = errors.Join(multiErr, fmt.Errorf("top-level block: DeprecationMessage must not be set when Deprecated is false"))
	}

	for name, attrS := range b.Attributes {
		if attrS == nil {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: attribute schema is nil", prefix, name))
			continue
		}
		multiErr = errors.Join(multiErr, attrS.internalValidate(name, prefix))

		// all attributes within a computed block must also be computed
		if b.Computed && !attrS.Computed {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: all attributes within computed blocks must also be computed", prefix, name))
		}
	}

	for name, blockS := range b.BlockTypes {
		if blockS == nil {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: block schema is nil", prefix, name))
			continue
		}

		if _, isAttr := b.Attributes[name]; isAttr {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: name defined as both attribute and child block type", prefix, name))
		} else if !validName.MatchString(name) {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: name may contain only lowercase letters, digits and underscores", prefix, name))
		}
		if !blockS.Deprecated && blockS.DeprecationMessage != "" {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: DeprecationMessage must not be set when Deprecated is false", prefix, name))
		}

		if blockS.MinItems < 0 || blockS.MaxItems < 0 {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: MinItems and MaxItems must both be greater than zero", prefix, name))
		}

		// any nested blocks within a computed block must also be computed
		if b.Computed && !blockS.Computed {

View on GitHub (pinned to d32a084675)