hashicorp/terraform · critical

top-level block schema is nil

Error message

top-level block schema is nil

What it means

Block.InternalValidate() is called on a nil *Block pointer. This is a development-time validation that runs when Terraform loads provider schemas during NewContext. A nil top-level schema block indicates a provider returned a nil schema or the schema was not properly initialized before validation. This error is seen by provider developers or due to internal Terraform bugs, not by end users writing HCL.

Solutions

  1. If you are a provider developer, ensure every resource and data source returns a non-nil schema.
  2. Update the provider plugin to the latest version — this may be a known bug fixed in a newer release.
  3. File an issue with the provider repository, including the resource type that triggers the error.
  4. If using terraform-plugin-framework, verify all schema definitions are complete and non-nil.

Example fix

// before (provider code) — nil schema returned
func (r *resource) Schema(ctx context.Context, req schema.Request) (schema.Response, error) {
    return schema.Response{}, nil  // nil schema
}

// after — return a complete schema
func (r *resource) Schema(ctx context.Context, req schema.Request) (schema.Response, error) {
    return schema.Response{
        Schema: schema.Schema{
            Attributes: map[string]schema.Attribute{...},
        },
    }, nil
}
Defensive patterns

Strategy: validation

Validate before calling

// Provider developers: call InternalValidate in unit tests
func TestResourceSchemaValid(t *testing.T) {
    schema := myResource().Schema(ctx)
    block := schemaBlockFromFramework(schema) // convert to *configschema.Block
    if err := block.InternalValidate(); err != nil {
        t.Fatalf("schema invalid: %v", err)
    }
}

// Guard against nil before calling:
if block == nil {
    return errors.New("schema is nil — provider returned no schema")
}

Type guard

func isNonNilBlock(b *configschema.Block) bool {
    return b != nil
}

Prevention

When it happens

Trigger: InternalValidate() is invoked on a Block that is nil. This happens when a provider plugin returns a nil schema for a resource/data source, or when Terraform's schema aggregation code passes a nil pointer into validation. Triggered during context creation (NewContext) when schemas are loaded.

Common situations: A provider plugin has a bug returning nil from its Schema() method. A custom Terraform fork or internal tooling constructs a schema tree with a nil root. A provider uses the terraform-plugin-sdk/terraform-plugin-framework incorrectly, leaving a schema unset. Rare Terraform core bug in schema aggregation.

Related errors


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

Appendix: source

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

import (
	"errors"
	"fmt"
	"regexp"

	"github.com/zclconf/go-cty/cty"
)

var validName = regexp.MustCompile(`^[a-z0-9_]+$`)

// InternalValidate returns an error if the receiving block and its child schema
// definitions have any inconsistencies with the documented rules for valid
// schema.
//
// This can be used within unit tests to detect when a given schema is invalid,
// and is run when terraform loads provider schemas during NewContext.
func (b *Block) InternalValidate() error {
	if b == nil {
		return fmt.Errorf("top-level block schema is nil")
	}
	return b.internalValidate("")
}

func (b *Block) internalValidate(prefix string) error {
	var multiErr error

	if prefix == "" && !b.Deprecated && b.DeprecationMessage != "" {
		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))

View on GitHub (pinned to d32a084675)