hashicorp/terraform · error
top-level block: DeprecationMessage must not be set when…
Error message
top-level block: DeprecationMessage must not be set when Deprecated is false
What it means
During schema validation, the top-level Block has a non-empty DeprecationMessage but Deprecated is false. These two fields must be consistent: DeprecationMessage is only meaningful when Deprecated is true. This is a provider-developer error caught when the provider schema is loaded and validated by Terraform core.
Solutions
- If using terraform-plugin-framework, set both DeprecationMessage and the deprecated flag consistently in your schema definition.
- If maintaining a custom schema struct, set b.Deprecated = true whenever b.DeprecationMessage != "".
- Review the provider code for the resource/data source whose schema triggers this and fix the field combination.
Example fix
// before — DeprecationMessage without Deprecated
&configschema.Block{
DeprecationMessage: "Use 'new_resource' instead",
// Deprecated not set → defaults to false
}
// after — both set consistently
&configschema.Block{
Deprecated: true,
DeprecationMessage: "Use 'new_resource' instead",
} Defensive patterns
Strategy: validation
Validate before calling
// Provider developers: validate deprecation field consistency
func validateDeprecationFields(b *configschema.Block) error {
if !b.Deprecated && b.DeprecationMessage != "" {
return errors.New("DeprecationMessage set but Deprecated is false")
}
return b.InternalValidate()
}
// Unit test gate:
func TestSchemaDeprecationConsistency(t *testing.T) {
if err := myResourceSchema().InternalValidate(); err != nil {
t.Fatal(err)
}
} Prevention
- Always set Deprecated: true when setting DeprecationMessage.
- Add InternalValidate() to provider test suites as a CI gate.
- When migrating schema frameworks, audit deprecation field semantics — they differ between SDK and framework.
When it happens
Trigger: A provider schema defines DeprecationMessage on the root block without setting Deprecated: true. The internalValidate check at the top level (prefix == "") catches this inconsistency. Triggered during NewContext when provider schemas are loaded.
Common situations: A provider developer sets DeprecationMessage expecting it to work standalone, not realizing Deprecated must also be true. Copy-paste from a nested block where the combination was valid. Framework abstraction that auto-populates one field but not the other. Schema migration from terraform-plugin-sdk to terraform-plugin-framework where field semantics differ.
Related errors
- : all attributes within computed blocks must also be…
- : attribute schema is nil
- : block schema is nil
- : name defined as both attribute and child block type
- : name may contain only lowercase letters, digits and…
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/69117209567f5c11.
Report an issue: GitHub.
Appendix: source
Thrown at internal/configs/configschema/internal_validate.go:33
// 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))
// 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))View on GitHub (pinned to d32a084675)