hashicorp/terraform · error

%s: attribute schema is nil

Error message

%s: attribute schema is nil

What it means

Thrown by Object.InternalValidate (internal_validate.go:213) when iterating over an Object schema's Attributes map and encountering a nil value for an attribute. InternalValidate is designed to catch provider schema construction bugs before the schema is used; a nil attribute pointer means the provider code built an incomplete or malformed NestedType/Object schema. This is a developer-time invariant check, not a user-input error.

Source

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

				continue
			}
			err = errors.Join(err, attrS.internalValidate(name, prefix))
		}
	}

	return err
}

func (o *Object) InternalValidate() error {
	var err error

	if o.Nesting == nestingModeInvalid {
		return fmt.Errorf("object schema nesting mode is invalid")
	}

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

	return err
}

View on GitHub (pinned to c9def3e214)

Solutions

  1. Inspect the InternalValidate error message: the %s placeholder names the attribute key whose value is nil — find that key in your schema construction code and ensure a non-nil *Attribute is assigned.
  2. Add a nil check in your schema builder before inserting into the Attributes map, or use a helper that never leaves attributes unset.
  3. Run InternalValidate inside provider unit tests (the doc comment says it is designed for that) so this surfaces in CI rather than at runtime.
  4. If generating schemas dynamically, validate the generator output with InternalValidate before returning it from the provider server.

Example fix

// before
obj := &configschema.Object{
    Nesting: configschema.NestingModeSingle,
    Attributes: map[string]*configschema.Attribute{
        "name": {Type: cty.String, Optional: true},
        "tags": nil, // bug: left nil
    },
}

// after
obj := &configschema.Object{
    Nesting: configschema.NestingModeSingle,
    Attributes: map[string]*configschema.Attribute{
        "name": {Type: cty.String, Optional: true},
        "tags": {Type: cty.Map(cty.String), Optional: true},
    },
}
Defensive patterns

Strategy: validation

Validate before calling

// Before exposing a schema, validate it; nil attribute pointers fail fast here
if err := block.InternalValidate(); err != nil {
    return nil, fmt.Errorf("provider schema is invalid: %w", err)
}
// Guard during construction so InternalValidate never sees nil:
for name, attr := range obj.Attributes {
    if attr == nil {
        return fmt.Errorf("attribute %q must not be nil", name)
    }
}

Type guard

func isCompleteObject(o *configschema.Object) bool {
    if o == nil || o.Attributes == nil {
        return false
    }
    for _, attr := range o.Attributes {
        if attr == nil {
            return false
        }
    }
    return true
}

Prevention

When it happens

Trigger: A provider plugin or schema-building code path constructs a configschema.Object (or NestedType with Nesting mode) whose Attributes map contains a key mapped to a nil *Attribute. Calling InternalValidate() on that object, or loading provider schemas during NewContext, triggers the check at line 211-214.

Common situations: Provider developers programmatically building block types with NestedType objects and forgetting to populate one attribute, or copy-paste schema construction that leaves a placeholder nil. Using cty.DynamicPseudoType in contexts where a concrete attribute should be. Schema generated from reflection or code-gen that omits a field.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/2b473d9a726db318. Report an issue: GitHub.