hashicorp/terraform · error
invalid value for
Error message
invalid value for %q: %s
What it means
Thrown by SDKLikeDefaults.ApplyTo in the cty.Bool case when strconv.ParseBool rejects the resolved string. HCL config values for bool attributes are already validated by HCL, so this error almost always comes from an environment variable or a Fallback default that is not a recognized bool literal. strconv.ParseBool only accepts 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False.
Solutions
- Change the env var to a strconv.ParseBool-accepted literal: "true"/"false" (or "1"/"0").
- Set the bool attribute directly in the backend block (HCL accepts true/false natively).
- If you maintain a backend, document the accepted bool spellings next to the EnvVars entry to prevent the yes/no trap.
- Unset the env var if the default ("false" when rawStr is empty) is what you want.
Example fix
# before export TF_SKIP_VERIFY="yes" # -> invalid value for "skip_credentials_validation" # after export TF_SKIP_VERIFY="true"
Defensive patterns
Strategy: validation
Validate before calling
// Validate bool env vars with the same rule ApplyTo uses.
func boolEnvOk(name string) error {
if v := os.Getenv(name); v != "" {
if _, err := strconv.ParseBool(v); err != nil {
return fmt.Errorf("env %s=%q is not a valid bool (want true/false/1/0)", name, v)
}
}
return nil
} Type guard
null
Try / catch
if _, err := defs.ApplyTo(cfg); err != nil {
// Distinguish bool-parse errors by substring if you want bespoke UX.
if strings.Contains(err.Error(), "invalid value for") {
return fmt.Errorf("a backend env var has an invalid bool value: %w", err)
}
return err
} Prevention
- Use only true/false (or 1/0) for boolean backend env vars — the same set strconv.ParseBool accepts.
- Avoid yes/no/on/off idioms in scripts that export Terraform backend config.
- Add a config-validation step in CI that parses every TF_BACKEND_* bool env var before invoking terraform.
When it happens
Trigger: An attribute typed cty.Bool has defs.EnvVars set; the user exports that env var with a value like "yes", "no", "enabled", "on", "off", or "y". ApplyTo resolves rawStr to that value, then strconv.ParseBool(rawStr) returns an error and the message is `invalid value for "<attrName>": <strconv error>`.
Common situations: Using common shell idioms (yes/no, on/off) for a boolean backend flag such as use_azuread_auth, skip_credentials_validation, or force_path_style. Also seen when an env var is accidentally set to a descriptive sentence or to a numeric other than 0/1.
Related errors
- invalid value for : must be a number
- argument is required
- attribute is required
- address argument is required
- building Storage Accounts client: %+v
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/142de110d04a0869.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/backendbase/sdklike.go:262
// also unset. Otherwise, rawStr contains a string representation of
// a value that we now need to convert back to the type that was
// originally wanted.
switch ty {
case cty.String:
retAttrs[attrName] = cty.StringVal(rawStr)
case cty.Bool:
if rawStr == "" {
rawStr = "false"
}
// Legacy SDK uses strconv.ParseBool and therefore tolerates a
// variety of different string representations of true and false,
// so we'll do the same here. The config itself can't use those
// alternate forms because HCL's definition of bool prevails there,
// but the environment variables can use any of these forms.
bv, err := strconv.ParseBool(rawStr)
if err != nil {
return cty.NilVal, fmt.Errorf("invalid value for %q: %s", attrName, err)
}
retAttrs[attrName] = cty.BoolVal(bv)
case cty.Number:
if rawStr == "" {
rawStr = "0"
}
// This case is a little trickier because cty.Number could be
// representing either an integer or a float, which each have
// different interpretations in the legacy SDK. Therefore we'll
// try integer first and use its result if successful, but then
// try float as a fallback if not.
if iv, err := strconv.ParseInt(rawStr, 0, 0); err == nil {
retAttrs[attrName] = cty.NumberIntVal(iv)
} else if fv, err := strconv.ParseFloat(rawStr, 64); err == nil {
retAttrs[attrName] = cty.NumberFloatVal(fv)
} else {
return cty.NilVal, fmt.Errorf("invalid value for %q: must be a number", attrName)View on GitHub (pinned to d32a084675)