What's Actually Happening

Terraform has variables defined in your configuration without default values, making them required inputs. When you run terraform plan or terraform apply without providing these required variables, Terraform blocks execution and prompts for input or shows an error.

The Error You'll See

``` Error: Missing required variable

on variables.tf line 5: 5: variable "aws_region" { 6: type = string 7: }

The root module input variable "aws_region" is not set, and has no default value. Use a -var or -var-file command line argument to provide a value for this variable. ```

Interactive prompt (if running without -auto-approve):

bash
var.aws_region
  Enter a value:

For variables with validation:

``` Error: Invalid value for variable

on variables.tf line 15: 15: variable "environment" { 16: type = string 17: validation { 18: condition = contains(["dev", "staging", "prod"], var.environment) 19: error_message = "Environment must be dev, staging, or prod." 20: } 21: }

Environment must be dev, staging, or prod.

This was checked by the validation rule at variables.tf:15,3-7. ```

Why This Happens

Required variable errors occur when:

  1. 1.No default value - Variable defined without a default
  2. 2.Not passed via command line - Missing -var or -var-file argument
  3. 3.Not in environment - TF_VAR_ prefixed environment variable not set
  4. 4.Not in terraform.tfvars - Standard variable file missing values
  5. 5.Validation failure - Variable value doesn't pass validation rules
  6. 6.Type mismatch - Passed value has wrong type
  7. 7.Sensitive variable - Variable marked sensitive cannot have default
  8. 8.Workspace mismatch - Wrong .tfvars file for current workspace

Step 1: Identify Required Variables

Find which variables are required:

```bash # List all variables and their requirements terraform console > var # Type 'var' to see available variables

# Or inspect the variables file cat variables.tf | grep -A10 "variable"

# Check for variables without defaults grep -B5 -A15 'variable "' variables.tf | grep -v "default" ```

Inspect variable definitions:

```hcl # This variable is REQUIRED (no default) variable "aws_region" { type = string # No default = required }

# This variable is OPTIONAL (has default) variable "instance_type" { type = string default = "t3.micro" }

# Sensitive variables cannot have defaults variable "db_password" { type = string sensitive = true # Cannot add default for sensitive variable } ```

Step 2: Provide Variables via Command Line

Pass required variables directly:

```bash # Single variable via -var terraform plan -var 'aws_region=us-east-1'

# Multiple variables terraform plan \ -var 'aws_region=us-east-1' \ -var 'environment=production' \ -var 'instance_count=3'

# For sensitive values, use environment variable (better security) export TF_VAR_db_password='my-secret-password' terraform plan ```

Step 3: Use Variable Files

Create and use .tfvars files:

```bash # Create terraform.tfvars (automatically loaded) cat > terraform.tfvars << 'EOF' aws_region = "us-east-1" environment = "production" instance_count = 3 EOF

# Terraform automatically loads terraform.tfvars terraform plan ```

Use custom variable files:

```bash # Create environment-specific file cat > environments/prod.tfvars << 'EOF' aws_region = "us-east-1" environment = "production" instance_count = 5 EOF

# Use with -var-file terraform plan -var-file=environments/prod.tfvars

# For development terraform plan -var-file=environments/dev.tfvars ```

Step 4: Set Variables via Environment

Use TF_VAR_ prefixed environment variables:

```bash # Set individual variables export TF_VAR_aws_region="us-east-1" export TF_VAR_environment="production" export TF_VAR_instance_count="3"

# Terraform automatically picks these up terraform plan

# For sensitive values (won't show in shell history) read -s TF_VAR_db_password export TF_VAR_db_password terraform apply ```

Step 5: Add Default Values to Variables

Make variables optional by adding defaults:

```hcl # Before - required variable variable "aws_region" { type = string }

# After - optional variable with default variable "aws_region" { type = string default = "us-east-1" }

# Complex type with default variable "tags" { type = map(string) default = { Environment = "dev" ManagedBy = "terraform" } }

# List with default variable "subnet_cidrs" { type = list(string) default = ["10.0.1.0/24", "10.0.2.0/24"] } ```

Step 6: Fix Variable Validation Errors

Handle validation rule failures:

```bash # Check what values are allowed cat variables.tf | grep -A20 "validation"

# Common validation patterns variable "environment" { type = string

validation { condition = contains(["dev", "staging", "prod"], var.environment) error_message = "Must be dev, staging, or prod." } }

variable "instance_count" { type = number

validation { condition = var.instance_count > 0 && var.instance_count <= 10 error_message = "Count must be between 1 and 10." } } ```

Provide valid values:

```bash # Use allowed value terraform plan -var 'environment=prod'

# Or update terraform.tfvars environment = "prod" # Valid value ```

Step 7: Fix Type Mismatch Errors

Handle type errors:

``` Error: Invalid value for variable

variable "instance_count" has type number, but value "three" is string ```

Fix type mismatches:

hcl
# In .tfvars file - use correct types
instance_count = 3       # number (no quotes)
aws_region     = "us-east-1"  # string (quotes)
enabled        = true    # bool (no quotes)
tags = {                 # map
  Name = "my-instance"
}
subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24"]  # list

On command line:

```bash # Number - no quotes terraform plan -var 'instance_count=3'

# String - quotes needed terraform plan -var 'aws_region="us-east-1"'

# Boolean - true/false without quotes terraform plan -var 'enabled=true'

# List - JSON format terraform plan -var 'subnet_cidrs=["10.0.1.0/24", "10.0.2.0/24"]'

# Map - JSON format terraform plan -var 'tags={"Name":"my-instance"}' ```

Step 8: Handle Sensitive Variables

For sensitive required variables:

hcl
variable "db_password" {
  type      = string
  sensitive = true
  # Cannot have default value
}

Provide sensitive values securely:

```bash # Environment variable (recommended) export TF_VAR_db_password='secret123'

# Or use .tfvars file NOT committed to git cat > secrets.tfvars << 'EOF' db_password = "secret123" EOF

# Add to .gitignore echo "secrets.tfvars" >> .gitignore

# Use the file terraform plan -var-file=secrets.tfvars ```

For CI/CD, use secret management:

yaml
# GitHub Actions
jobs:
  terraform:
    steps:
      - name: Terraform Plan
        env:
          TF_VAR_db_password: ${{ secrets.DB_PASSWORD }}
        run: terraform plan

Step 9: Workspace-Specific Variables

Use different variables per workspace:

```bash # Create workspace-specific .tfvars # terraform.tfvars automatically loaded # but you can also use workspace-specific naming

# For workspace 'production' cat > production.tfvars << 'EOF' instance_count = 5 environment = "production" EOF

# For workspace 'dev' cat > dev.tfvars << 'EOF' instance_count = 1 environment = "dev" EOF

# Select workspace and use matching file terraform workspace select production terraform plan -var-file=production.tfvars ```

Auto-select based on workspace:

```hcl locals { # Automatically use workspace-specific values env_vars = { dev = { instance_count = 1 } staging = { instance_count = 2 } prod = { instance_count = 5 } }

instance_count = local.env_vars[terraform.workspace].instance_count }

resource "aws_instance" "main" { count = local.instance_count } ```

Step 10: Debug Variable Resolution

Check variable values:

```bash # Use console to inspect terraform console > var.aws_region > var.environment > var.instance_count

# Debug mode shows variable loading export TF_LOG=DEBUG terraform plan 2>&1 | grep -i "var|variable" ```

Verify the Fix

After providing required variables:

```bash # Verify variables loaded correctly terraform console > var.aws_region "us-east-1"

# Run plan without errors terraform plan

# Should not see missing variable errors ```

Check all variables are set:

bash
# List variables in state
terraform console
> keys(var)

Prevention Best Practices

Always document required variables:

```hcl variable "aws_region" { type = string description = "AWS region for infrastructure deployment (required)" }

variable "environment" { type = string description = "Deployment environment: dev, staging, or prod"

validation { condition = contains(["dev", "staging", "prod"], var.environment) error_message = "Environment must be dev, staging, or prod." } } ```

Create example variable files:

```bash # Create example file users can copy cat > terraform.tfvars.example << 'EOF' aws_region = "us-east-1" environment = "dev" instance_count = 1 # db_password - set via environment: TF_VAR_db_password EOF

# Document in README ```

Use auto.tfvars for automatic loading:

```bash # Files named *.auto.tfvars are automatically loaded cat > production.auto.tfvars << 'EOF' environment = "production" EOF

# No need to specify -var-file terraform plan ```