{"record":{"id":"69117209567f5c11","repo":"hashicorp/terraform","slug":"top-level-block-deprecationmessage-must-not-be-se","errorCode":null,"errorMessage":"top-level block: DeprecationMessage must not be set when Deprecated is false","messagePattern":"top-level block: DeprecationMessage must not be set when Deprecated is false","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configs/configschema/internal_validate.go","lineNumber":33,"sourceCode":"\n// InternalValidate returns an error if the receiving block and its child schema\n// definitions have any inconsistencies with the documented rules for valid\n// schema.\n//\n// This can be used within unit tests to detect when a given schema is invalid,\n// and is run when terraform loads provider schemas during NewContext.\nfunc (b *Block) InternalValidate() error {\n\tif b == nil {\n\t\treturn fmt.Errorf(\"top-level block schema is nil\")\n\t}\n\treturn b.internalValidate(\"\")\n}\n\nfunc (b *Block) internalValidate(prefix string) error {\n\tvar multiErr error\n\n\tif prefix == \"\" && !b.Deprecated && b.DeprecationMessage != \"\" {\n\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))","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/configs/configschema/internal_validate.go#L15-L51","documentation":"At the top-level block only (prefix==\"\"), DeprecationMessage is non-empty while Deprecated is false. The schema contract (documented on Block.DeprecationMessage) is that the message is valid only when Deprecated is true; setting the message without the flag is contradictory. Caught at lines 32-34 before recursing.","triggerScenarios":"A provider schema sets b.DeprecationMessage = \"use x instead\" but forgets b.Deprecated = true on the root block.","commonSituations":"Adding a deprecation notice incrementally, copy-paste from a deprecated block missing the flag, SDK auto-generation mismatch.","solutions":["Set Deprecated = true alongside DeprecationMessage on the top-level Block.","Or clear DeprecationMessage if the resource is not actually deprecated.","Add a schema-builder helper that enforces the pairing invariant."],"exampleFix":"// before\nschema := &configschema.Block{\n    DeprecationMessage: \"use 'foo_v2' instead\",\n}\n\n// after\nschema := &configschema.Block{\n    Deprecated:         true,\n    DeprecationMessage: \"use 'foo_v2' instead\",\n}","handlingStrategy":"validation","validationCode":"// In a schema builder helper, assert the invariant:\n// if DeprecationMessage != \"\" then Deprecated must be true.\nfunc checkDeprecation(b *configschema.Block) error {\n    if !b.Deprecated && b.DeprecationMessage != \"\" {\n        return errors.New(\"DeprecationMessage set without Deprecated=true\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set Deprecated and DeprecationMessage together in one edit.","Add a unit test/linter that enforces the pairing on the root block."],"tags":["configschema","provider-sdk","deprecation","validation"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}