hashicorp/terraform · error

invalid value for %q: %s

Error message

invalid value for %q: %s

What it means

Thrown by SDKLikeDefaults.ApplyTo when an attribute typed cty.Bool receives a string (typically from an environment variable) that strconv.ParseBool cannot interpret. The legacy SDK allowed environment variables to use alternate boolean spellings (1, t, TRUE, etc.) and this mirrors that, but anything outside ParseBool's accepted set fails.

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 c9def3e214)

Solutions

  1. Set the boolean environment variable to one of: true, false, 1, 0, or any strconv.ParseBool-accepted form.
  2. Define the value directly in the backend block as a native HCL bool (true/false) instead of relying on the env var.
  3. Remove stray quotes or whitespace from the environment variable value.

Example fix

# before
export SOME_BACKEND_BOOL=yes
# after
export SOME_BACKEND_BOOL=true
Defensive patterns

Strategy: validation

Validate before calling

// Validate a bool-providing env var against strconv.ParseBool's accepted set before init.
func validBoolEnv(name string) bool {
    v := os.Getenv(name)
    if v == "" {
        return true // unset is fine if there's a config/fallback
    }
    _, err := strconv.ParseBool(v)
    return err == nil
}

Try / catch

val, err := defaults.ApplyTo(config)
if err != nil {
    if strings.Contains(err.Error(), "invalid value for") {
        // surface a hint about the expected bool/number format
    }
    return err
}

Prevention

When it happens

Trigger: A boolean backend attribute is populated from an environment variable whose value is not parseable as a bool (e.g. 'yes', 'on', '"true"', or an arbitrary string). ParseBool accepts: 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False.

Common situations: Setting an env var like TF_VAR_... or a backend bool env var to 'yes'/'on' (common in shell scripts) instead of 'true'; quoting the value; copy-paste typos.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/142de110d04a0869. Report an issue: GitHub.