hashicorp/terraform · warning
Invalid value
Error message
Invalid value: %s
What it means
Thrown during interactive (UI) prompting for a required provider/resource attribute that the user left unset. Meta.inputForSchema reads a raw string from UIInput, wraps it as cty.StringVal, then convert.Convert attempts to coerce it to the attribute's declared type (number, bool, list, etc.). On failure the offending value is surfaced as a diagnostic and the prompt loops, so this is a recoverable per-attempt warning rather than a fatal error. It exists because the CLI cannot statically know whether a typed-in string will parse until conversion is attempted.
Solutions
- Re-enter the value at the prompt in the correct primitive type (a bare number like 5, or true/false for bool).
- Pre-supply the value non-interactively with -var or a *.tfvars file / TF_VAR_* environment variable so the attribute is no longer null and inputForSchema skips prompting.
- If automating, provide all required inputs via -input=false plus -var/-var-file to avoid the prompt entirely.
- Check the attribute's declared type in the provider schema (terraform providers schema -json) and match the literal syntax exactly.
Example fix
// before: prompted for a number attribute, typed 'abc' // after: supply via var file count = 3 // or on CLI terraform apply -var="replicas=3" -input=false
Defensive patterns
Strategy: validation
Validate before calling
// Validate the raw string against the attribute type before submitting.
func parsePrimitive(raw string, t cty.Type) (cty.Value, error) {
v := cty.StringVal(raw)
return convert.Convert(v, t) // returns err identical to the CLI path
}
// caller:
if _, err := parsePrimitive(input, attrS.Type); err != nil {
log.Printf("please re-enter a valid %s", attrS.Type.FriendlyName())
} Type guard
// guard before prompting: only primitive types are promptable
func isPromptable(attrS *configschema.Attribute) bool {
return attrS.Required && attrS.Type.IsPrimitiveType()
} Prevention
- Pre-supply all required variables via -var / *.tfvars / TF_VAR_* so inputForSchema never prompts.
- Run non-interactive CI with -input=false to fail fast on missing values instead of looping.
- Validate configurations with terraform validate before plan/apply.
When it happens
Trigger: Meta.inputForSchema is called for an attribute where attrS.Required is true, the given value is null, and attrS.Type.IsPrimitiveType(). The user answers the InputOpts prompt with a value that convert.Convert(val, attrS.Type) rejects (e.g. 'abc' for a number attribute, 'yes' for a bool, malformed input for a type that is not cty.String).
Common situations: Running terraform plan/apply without -var or var files for variables backed by required provider attributes; CI shells that accidentally feed interactive stdin; supplying a value like 'true'/'false' where a number is required; pasting values with stray whitespace or quotes.
Related errors
- A managed resource address is required. Importing into a…
- at most 1 action can be invoked per operation
- blank output
- Can't serialize backend configuration as JSON
- can't set both encryption_key and kms_encryption_key
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/0c58827b6853eca0.
Report an issue: GitHub.
Appendix: source
Thrown at internal/command/meta_config.go:409
input := m.UIInput()
for _, name := range names {
attrS := schema.Attributes[name]
for {
strVal, err := input.Input(context.Background(), &terraform.InputOpts{
Id: name,
Query: name,
Description: attrS.Description,
})
if err != nil {
return cty.UnknownVal(schema.ImpliedType()), fmt.Errorf("%s: %s", name, err)
}
val := cty.StringVal(strVal)
val, err = convert.Convert(val, attrS.Type)
if err != nil {
m.showDiagnostics(fmt.Errorf("Invalid value: %s", err))
continue
}
retVals[name] = val
break
}
}
return cty.ObjectVal(retVals), nil
}
// configSources returns the source cache from the receiver's config loader,
// which the caller must not modify.
//
// If a config loader has not yet been instantiated then no files could have
// been loaded already, so this method returns a nil map in that case.
func (m *Meta) configSources() map[string][]byte {
if m.configLoader == nil {View on GitHub (pinned to d32a084675)