{"record":{"id":"ac92ca919d5cd9de","repo":"hashicorp/terraform","slug":"s-s-cannot-set-both-optional-and-required","errorCode":null,"errorMessage":"%s%s: cannot set both Optional and Required","messagePattern":"(.+?)(.+?): cannot set both Optional and Required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configs/configschema/internal_validate.go","lineNumber":150,"sourceCode":"\tif a == nil {\n\t\treturn fmt.Errorf(\"attribute schema is nil\")\n\t}\n\treturn a.internalValidate(name, \"\")\n}\n\nfunc (a *Attribute) internalValidate(name, prefix string) error {\n\tvar err error\n\n\t/* FIXME: this validation breaks certain existing providers and cannot be enforced without coordination.\n\tif !validName.MatchString(name) {\n\t\terr = errors.Join(err, fmt.Errorf(\"%s%s: name may contain only lowercase letters, digits and underscores\", prefix, name))\n\t}\n\t*/\n\tif !a.Optional && !a.Required && !a.Computed {\n\t\terr = errors.Join(err, fmt.Errorf(\"%s%s: must set Optional, Required or Computed\", prefix, name))\n\t}\n\tif a.Optional && a.Required {\n\t\terr = errors.Join(err, fmt.Errorf(\"%s%s: cannot set both Optional and Required\", prefix, name))\n\t}\n\tif a.Computed && a.Required {\n\t\terr = errors.Join(err, fmt.Errorf(\"%s%s: cannot set both Computed and Required\", prefix, name))\n\t}\n\tif !a.Deprecated && a.DeprecationMessage != \"\" {\n\t\terr = errors.Join(err, fmt.Errorf(\"%s%s: DeprecationMessage must not be set when Deprecated is false\", prefix, name))\n\t}\n\n\tif a.Type == cty.NilType && a.NestedType == nil {\n\t\terr = errors.Join(err, fmt.Errorf(\"%s%s: either Type or NestedType must be defined\", prefix, name))\n\t}\n\n\tif a.Type != cty.NilType {\n\t\tif a.NestedType != nil {\n\t\t\terr = errors.Join(fmt.Errorf(\"%s: Type and NestedType cannot both be set\", name))\n\t\t}\n\t}\n","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/configs/configschema/internal_validate.go#L132-L168","documentation":"Raised when an Attribute has both Optional and Required set to true. These flags are mutually exclusive: Optional permits omission, Required forbids it — together they are contradictory. The validator at internal_validate.go:149 enforces exclusivity.","triggerScenarios":"An Attribute struct literal with both Optional: true and Required: true. internalValidate reaches line 149 and the condition holds.","commonSituations":"Copy-pasting an Optional attribute and adding Required without removing Optional; merging two schema fragments each setting a different flag; confusing 'Optional but with a default' with 'Required'.","solutions":["Decide whether the user may omit the value: keep Optional (drop Required) or keep Required (drop Optional).","If you want 'user may override a provider default', use Optional+Computed, not Optional+Required.","Add a schema linter rule that rejects simultaneous Optional and Required."],"exampleFix":"// before\n\"name\": {Type: cty.String, Optional: true, Required: true}\n\n// after\n\"name\": {Type: cty.String, Required: true}","handlingStrategy":"validation","validationCode":"func assertNotOptionalAndRequired(a *configschema.Attribute) error {\n    if a.Optional && a.Required {\n        return fmt.Errorf(\"cannot set both Optional and Required\")\n    }\n    return nil\n}","typeGuard":"func isMutuallyConsistent(a *configschema.Attribute) bool {\n    return !(a.Optional && a.Required)\n}","tryCatchPattern":null,"preventionTips":["Treat Optional and Required as mutually exclusive radio buttons.","For 'user may override a provider default', use Optional+Computed, not Optional+Required.","Lint to reject attributes setting both flags."],"tags":["configschema","attribute","optional","required","mutual-exclusion","validation"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}