Bird
Raised Fist0
Terraformcloud~15 mins

Variable validation blocks in Terraform - Deep Dive

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Overview - Variable validation blocks
What is it?
Variable validation blocks in Terraform are rules you add inside variable definitions to check if the values given are correct. They help make sure inputs meet certain conditions before Terraform uses them. This prevents mistakes early by stopping wrong values from being accepted. Validation blocks give clear messages to explain what went wrong.
Why it matters
Without validation blocks, wrong or unexpected values can cause Terraform to create broken or insecure infrastructure. This can lead to downtime, security risks, or wasted resources. Validation blocks catch errors early, saving time and avoiding costly fixes later. They make Terraform configurations safer and more reliable.
Where it fits
Before learning validation blocks, you should understand Terraform variables and how to define them. After mastering validation, you can learn about advanced input handling like dynamic blocks and custom modules that rely on validated inputs.
Mental Model
Core Idea
Variable validation blocks act like gatekeepers that check if input values meet rules before Terraform uses them.
Think of it like...
It's like a security guard at a club entrance checking IDs to make sure only people of the right age get in. If the ID doesn't match the rules, the guard stops them and explains why.
┌─────────────────────────────┐
│        Variable Input        │
└─────────────┬───────────────┘
              │
      ┌───────▼────────┐
      │ Validation Block│
      └───────┬────────┘
              │ Passes? ── No ──> Error message shown
              │
             Yes
              │
      ┌───────▼────────┐
      │ Use Variable   │
      └────────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Terraform Variables
🤔
Concept: Learn what Terraform variables are and why they are used.
Terraform variables let you customize your infrastructure by providing inputs. You define variables in your configuration and assign values when running Terraform. This makes your code reusable and flexible.
Result
You can write one Terraform configuration and use different values to create different setups.
Knowing variables is essential because validation blocks only work inside variable definitions.
2
FoundationBasic Variable Validation Syntax
🤔
Concept: Introduce the syntax and structure of a validation block inside a variable.
Inside a variable block, you add a validation block with a condition and an error message. The condition is an expression that must be true for the input to be accepted. If false, Terraform shows the error message and stops.
Result
Terraform rejects invalid inputs with clear messages before applying changes.
Understanding the syntax lets you start protecting your variables from bad inputs.
3
IntermediateCommon Validation Conditions
🤔Before reading on: do you think you can check if a number is positive or if a string matches a pattern? Commit to your answer.
Concept: Learn how to write common conditions like checking number ranges or string formats.
You can use expressions like var.value > 0 to check numbers or can use regex() to check string patterns. For example, to ensure a port number is between 1024 and 65535, you write a condition that checks this range.
Result
You can enforce rules like 'must be positive' or 'must look like an email' on inputs.
Knowing how to write conditions lets you tailor validation to your specific needs.
4
IntermediateUsing Validation with Complex Types
🤔Before reading on: can you guess if validation works only on simple types or also on lists and maps? Commit to your answer.
Concept: Validation blocks can check complex types like lists and maps using functions and expressions.
For example, you can check if a list has at least one item or if all map values meet a condition. Using functions like length() and alltrue(), you can write conditions for these types.
Result
You can validate structured inputs, not just single values.
Understanding this expands validation to more realistic and complex configurations.
5
IntermediateCustom Error Messages for Clarity
🤔
Concept: Learn how to write helpful error messages that explain what went wrong.
The error_message field in validation blocks lets you write clear instructions. Instead of a generic error, you can say exactly what the user must fix, like 'Port must be between 1024 and 65535'.
Result
Users get clear feedback, making it easier to fix input mistakes.
Good error messages improve user experience and reduce confusion.
6
AdvancedValidation in Modules for Reusability
🤔Before reading on: do you think validation blocks inside modules affect only that module or the whole Terraform run? Commit to your answer.
Concept: Using validation inside modules ensures inputs to modules are correct wherever they are used.
When you write reusable modules, adding validation blocks inside module variables protects the module from bad inputs. This makes modules safer and easier to share.
Result
Modules reject invalid inputs early, preventing errors in larger projects.
Knowing this helps build robust, reusable Terraform modules.
7
ExpertLimitations and Workarounds of Validation Blocks
🤔Before reading on: do you think validation blocks can access other variables or resources? Commit to your answer.
Concept: Validation blocks only see the variable value itself and cannot reference other variables or resources, which limits some checks.
Because validation runs before apply, it cannot check dynamic or external state. To work around this, you can use pre-apply scripts or custom Terraform providers for complex validation.
Result
You understand when validation blocks are not enough and need other tools.
Knowing these limits prevents frustration and guides you to proper validation strategies.
Under the Hood
Terraform evaluates validation blocks during the plan phase after variable values are assigned but before any resources are created. It runs the condition expression in Terraform's expression language. If the condition returns false, Terraform stops and shows the error message. This prevents invalid inputs from reaching resource creation.
Why designed this way?
Validation blocks were designed to catch errors early in the workflow to avoid costly mistakes during apply. They are limited to variable scope to keep evaluation simple and fast. More complex validation would require runtime state, which is not available at this stage.
┌───────────────┐
│ User Provides │
│ Variable Value│
└───────┬───────┘
        │
┌───────▼─────────────┐
│ Terraform Plan Phase │
│  ┌───────────────┐  │
│  │Validation Block│  │
│  └───────┬───────┘  │
│          │ Condition │
│          ▼          │
│    True ──> Continue│
│    False ─> Error   │
└─────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Do validation blocks run during Terraform apply or plan? Commit to your answer.
Common Belief:Validation blocks run during apply and can check resource states.
Tap to reveal reality
Reality:Validation blocks run during the plan phase before apply and cannot access resource states or other variables.
Why it matters:Believing validation runs during apply leads to expecting dynamic checks that are impossible, causing confusion and errors.
Quick: Can validation blocks modify variable values if invalid? Commit to your answer.
Common Belief:Validation blocks can fix or change invalid inputs automatically.
Tap to reveal reality
Reality:Validation blocks only check conditions; they do not modify values. If invalid, Terraform stops with an error.
Why it matters:Expecting automatic fixes can cause overlooked errors and broken infrastructure.
Quick: Do validation blocks support referencing other variables or resources? Commit to your answer.
Common Belief:Validation blocks can reference other variables or resources to validate complex conditions.
Tap to reveal reality
Reality:Validation blocks cannot reference other variables or resources because they run before those are available.
Why it matters:Trying to reference unavailable data causes errors and blocks Terraform runs.
Quick: Are validation blocks mandatory for all variables? Commit to your answer.
Common Belief:All variables must have validation blocks to work properly.
Tap to reveal reality
Reality:Validation blocks are optional and only needed when you want to enforce rules on inputs.
Why it matters:Thinking validation is mandatory may lead to unnecessary complexity or confusion.
Expert Zone
1
Validation expressions must be pure and cannot have side effects or depend on runtime state, which limits their complexity.
2
Validation error messages can use interpolation to include the invalid value, improving clarity for users.
3
Stacked validations in modules can create layered input checks, but ordering and error clarity require careful design.
When NOT to use
Avoid validation blocks when you need to check conditions involving other variables, resources, or runtime state. Instead, use Terraform's pre-apply scripts, external validation tools, or custom providers for complex validation.
Production Patterns
In production, validation blocks are used extensively in shared modules to enforce input contracts. Teams combine validation with documentation and CI checks to ensure inputs are correct before deployment.
Connections
Input Validation in Software Development
Validation blocks in Terraform are a specific case of input validation common in programming and software design.
Understanding general input validation principles helps grasp why Terraform enforces rules early to prevent errors.
Static Type Checking
Validation blocks complement Terraform's type system by adding custom rules beyond simple types.
Knowing static type checking clarifies why validation is needed for rules that types alone cannot enforce.
Quality Control in Manufacturing
Validation blocks act like quality control checkpoints ensuring inputs meet standards before production.
Seeing validation as quality control helps appreciate its role in preventing defects and costly fixes.
Common Pitfalls
#1Trying to reference other variables inside a validation block condition.
Wrong approach:validation { condition = var.other_variable == "value" error_message = "Must match other variable" }
Correct approach:validation { condition = length(var.value) > 0 error_message = "Value cannot be empty" }
Root cause:Validation blocks run before other variables are resolved, so referencing them causes errors.
#2Writing a condition that always returns true or false due to syntax errors.
Wrong approach:validation { condition = var.port > 1024 && error_message = "Port must be above 1024" }
Correct approach:validation { condition = var.port > 1024 error_message = "Port must be above 1024" }
Root cause:Missing part of the condition or syntax errors cause the condition to not evaluate properly.
#3Assuming validation blocks fix invalid inputs automatically.
Wrong approach:validation { condition = var.count >= 1 error_message = "Count too low, setting to 1" }
Correct approach:validation { condition = var.count >= 1 error_message = "Count must be at least 1" }
Root cause:Validation only checks conditions; it does not modify inputs.
Key Takeaways
Variable validation blocks in Terraform check input values early to prevent errors during infrastructure creation.
They use simple conditions and clear error messages to guide users to provide correct inputs.
Validation blocks run during the plan phase and cannot reference other variables or resources.
They are optional but highly recommended for reusable modules and production code to improve reliability.
Understanding their limits helps choose the right validation strategy for complex scenarios.

Practice

(1/5)
1. What is the main purpose of a validation block inside a Terraform variable?
easy
A. To check if the input value meets specific rules before applying the configuration
B. To assign a default value to the variable
C. To declare the variable type
D. To output the variable value after deployment

Solution

  1. Step 1: Understand variable validation purpose

    The validation block is used to enforce rules on input values to prevent invalid configurations.
  2. Step 2: Differentiate from other variable features

    Default values assign fallback values, type declares data type, and output shows results, but validation specifically checks input correctness.
  3. Final Answer:

    To check if the input value meets specific rules before applying the configuration -> Option A
  4. Quick Check:

    Validation block purpose = input checking [OK]
Hint: Validation blocks check inputs before use [OK]
Common Mistakes:
  • Confusing validation with default value assignment
  • Thinking validation outputs variable values
  • Mixing validation with type declaration
2. Which of the following is the correct syntax to add a validation block inside a Terraform variable?
easy
A. variable "example" { validate { condition = length(var.example) > 0 error = "Must not be empty" } }
B. variable "example" { validation { condition = length(var.example) > 0 error_message = "Must not be empty" } }
C. variable "example" { validation { check = length(var.example) > 0 message = "Must not be empty" } }
D. variable "example" { validation { condition = length(example) > 0 error_message = "Must not be empty" } }

Solution

  1. Step 1: Identify correct block and attribute names

    The correct block is validation with attributes condition and error_message.
  2. Step 2: Check variable references and syntax

    Inside the condition, use var.example to refer to the variable value. variable "example" { validation { condition = length(var.example) > 0 error_message = "Must not be empty" } } matches this exactly.
  3. Final Answer:

    variable "example" { validation { condition = length(var.example) > 0 error_message = "Must not be empty" } } -> Option B
  4. Quick Check:

    Validation syntax = correct block and attributes [OK]
Hint: Use 'validation' block with 'condition' and 'error_message' [OK]
Common Mistakes:
  • Using 'validate' instead of 'validation'
  • Using wrong attribute names like 'check' or 'error'
  • Referencing variable without 'var.' prefix
3. Given this variable declaration:
variable "port" {
  type = number
  validation {
    condition     = var.port >= 1024 && var.port <= 65535
    error_message = "Port must be between 1024 and 65535"
  }
}

What happens if you set port = 80 when applying Terraform?
medium
A. Terraform will apply successfully with port 80
B. Terraform will prompt to enter a valid port
C. Terraform will ignore the validation and use default port
D. Terraform will fail with error: Port must be between 1024 and 65535

Solution

  1. Step 1: Analyze the validation condition

    The condition requires the port to be between 1024 and 65535 inclusive.
  2. Step 2: Check the input value against the condition

    Port 80 is less than 1024, so the condition fails.
  3. Step 3: Understand Terraform behavior on validation failure

    Terraform stops and shows the error message from error_message.
  4. Final Answer:

    Terraform will fail with error: Port must be between 1024 and 65535 -> Option D
  5. Quick Check:

    Validation fails = error message shown [OK]
Hint: Validation blocks stop apply if condition is false [OK]
Common Mistakes:
  • Assuming Terraform applies anyway
  • Thinking default values are used automatically
  • Expecting interactive prompts for invalid input
4. Identify the error in this variable validation block:
variable "env" {
  type = string
  validation {
    condition     = var.env == "dev" || "prod"
    error_message = "env must be 'dev' or 'prod'"
  }
}
medium
A. Validation blocks cannot use logical OR operators
B. The error_message attribute is misspelled
C. The condition syntax is incorrect; it should compare both values explicitly
D. The variable type should be list, not string

Solution

  1. Step 1: Review the condition expression

    The condition var.env == "dev" || "prod" is invalid because "prod" alone is always true.
  2. Step 2: Correct the condition syntax

    It should be var.env == "dev" || var.env == "prod" to compare both values explicitly.
  3. Final Answer:

    The condition syntax is incorrect; it should compare both values explicitly -> Option C
  4. Quick Check:

    Logical OR needs full comparisons [OK]
Hint: Use full comparisons on both sides of OR [OK]
Common Mistakes:
  • Writing incomplete logical expressions
  • Assuming string alone works as condition
  • Confusing error_message spelling
5. You want to validate a list variable users so it must have at least 2 unique names and none can be empty strings. Which validation block correctly enforces this?
hard
A. validation { condition = length(var.users) >= 2 && length(distinct(var.users)) == length(var.users) && alltrue([for u in var.users : u != ""]) error_message = "Users must have 2+ unique non-empty names" }
B. validation { condition = length(var.users) > 2 && distinct(var.users) != [] error_message = "Users must have 2+ unique names" }
C. validation { condition = length(var.users) >= 2 && var.users != [""] error_message = "Users must not be empty" }
D. validation { condition = length(var.users) >= 2 && length(var.users) == length(distinct(var.users)) error_message = "Users must have unique names" }

Solution

  1. Step 1: Check list length and uniqueness

    Condition requires at least 2 items and all must be unique, so length(var.users) >= 2 and length(distinct(var.users)) == length(var.users) ensure this.
  2. Step 2: Ensure no empty strings

    The alltrue([for u in var.users : u != ""]) checks every user is not empty.
  3. Step 3: Compare options

    validation { condition = length(var.users) >= 2 && length(distinct(var.users)) == length(var.users) && alltrue([for u in var.users : u != ""]) error_message = "Users must have 2+ unique non-empty names" } includes all these checks correctly; others miss empty string check or uniqueness properly.
  4. Final Answer:

    validation { condition = length(var.users) >= 2 && length(distinct(var.users)) == length(var.users) && alltrue([for u in var.users : u != ""]) error_message = "Users must have 2+ unique non-empty names" } -> Option A
  5. Quick Check:

    All conditions combined = validation { condition = length(var.users) >= 2 && length(distinct(var.users)) == length(var.users) && alltrue([for u in var.users : u != ""]) error_message = "Users must have 2+ unique non-empty names" } [OK]
Hint: Combine length, distinct, and alltrue for list validation [OK]
Common Mistakes:
  • Missing empty string check
  • Using > 2 instead of >= 2 for minimum count
  • Not verifying uniqueness correctly