hashicorp/terraform · error

attribute is required

Error message

attribute %q is required

What it means

Thrown by backendbase.SDKLikeRequiredWithEnvDefault, a helper that emulates the legacy Terraform SDK's required-string-with-env-fallback behavior. It returns this error only when the supplied value is empty AND every fallback environment variable is also empty/unset. It exists to give backend authors a single call that both resolves env defaults and enforces presence.

Solutions

  1. Set the attribute directly in the backend {} block so v is non-empty before the helper runs.
  2. Export one of the fallback env vars named in envNames with a non-empty value (e.g. export ARM_STORAGE_ACCOUNT=...).
  3. If calling SDKLikeRequiredWithEnvDefault from your own backend code, verify the envNames slice still matches the env vars your users expect after any rename.
  4. Check for trailing whitespace or quoted-empty secrets in CI that resolve the env var to an empty string.

Example fix

// before: backend block missing storage_account_name
backend "azurerm" {
  container_name = "tfstate"
}
// after
backend "azurerm" {
  resource_group_name  = "rg-tf"
  storage_account_name = "mystgacct"
  container_name       = "tfstate"
  key                  = "prod.terraform.tfstate"
}
Defensive patterns

Strategy: validation

Validate before calling

// Before calling SDKLikeRequiredWithEnvDefault, resolve and check yourself.
func resolveRequired(attrPath, v string, envNames ...string) (string, error) {
    if v == "" {
        for _, n := range envNames {
            if e := strings.TrimSpace(os.Getenv(n)); e != "" {
                v = e
                break
            }
        }
    }
    if v == "" {
        return "", fmt.Errorf("attribute %q is required (checked config + %v)", attrPath, envNames)
    }
    return v, nil
}

Type guard

null

Try / catch

// SDKLikeRequiredWithEnvDefault returns (string, error); treat empty-result-with-nil-err as impossible.
val, err := backendbase.SDKLikeRequiredWithEnvDefault("bucket", cfg.Bucket, "AWS_BUCKET", "TF_BUCKET")
if err != nil {
    return fmt.Errorf("backend init: %w", err)
}
cfg.Bucket = val

Prevention

When it happens

Trigger: Calling SDKLikeRequiredWithEnvDefault(attrPath, v, envNames...) where v == "" and os.Getenv(name) returns "" for every name in envNames. This typically happens inside a backend's Configure() while reading a schema attribute such as bucket, key, or region.

Common situations: The backend block in terraform configuration omits a required argument (e.g. azurerm backend missing storage_account_name) and the matching env var (e.g. ARM_STORAGE_ACCOUNT) is also unset. Also seen in CI when the secret feeding the env var was not injected, or after a backend schema migration that renamed an env var.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/ad3fa8158aee2817. Report an issue: GitHub.

Appendix: source

Thrown at internal/backend/backendbase/sdklike.go:155

			v = os.Getenv(envName)
			if v != "" {
				return v
			}
		}
	}
	return v
}

// SDKLikeRequiredWithEnvDefault is a convenience wrapper around
// [SDKLikeEnvDefault] which returns an error if the result is still the
// empty string even after trying all of the fallback environment variables.
//
// This wrapper requires an additional argument specifying the attribute name
// just because that becomes part of the returned error message.
func SDKLikeRequiredWithEnvDefault(attrPath string, v string, envNames ...string) (string, error) {
	ret := SDKLikeEnvDefault(v, envNames...)
	if ret == "" {
		return "", fmt.Errorf("attribute %q is required", attrPath)
	}
	return ret, nil
}

// SDKLikeDefaults captures legacy-SDK-like default values to help fill the
// gap in abstraction level between the legacy SDK and Terraform's own
// configuration schema model.
type SDKLikeDefaults map[string]SDKLikeDefault

type SDKLikeDefault struct {
	EnvVars  []string
	Fallback string

	// Required is for situations where an argument is optional to set
	// in the configuration but _must_ eventually be set through the
	// combination of the configuration and the environment variables
	// in this object.
	//

View on GitHub (pinned to d32a084675)