Learn how to troubleshoot and resolve the "Error: Variables not allowed" issue in Terraform when running a plan.
The Terraform error message "Error: Variables not allowed" usually means you're trying to use a variable in a place where Terraform doesn't permit it. This article explains common causes of this error and provides solutions to fix them. It covers issues like using variables in output values, terraform
blocks, typos, incorrect data retrieval from lists and maps, and variable scope problems, particularly with modules. An example illustrating the solution for using variables in output values is also provided. If you're still facing the error after reading this guide, please share the relevant parts of your Terraform code for further assistance.
The error message "Error: Variables not allowed" in Terraform typically arises when you try to use a variable in a place where Terraform doesn't expect or allow them. Here's a breakdown of the common causes and how to fix them:
1. Variables in Output Values:
output
block's value
argument. Terraform outputs are meant to expose values determined after resources are created, not just echo input variables.locals
block to store its value and then reference the local variable in your output.2. Variables in terraform
Blocks (e.g., Backend Configuration):
terraform { backend {} }
. These blocks configure Terraform's behavior and are evaluated before variable values are fully known.-backend-config="key=value"
.TF_VAR_access_key
)..tfvars
extension) to provide values for backend settings.3. Typos or Incorrect Syntax:
var.my_variable
).4. Incorrect Data Retrieval (Especially with Lists/Maps):
length(var.my_list) > 0 ? var.my_list[0] : null
) to prevent errors when dealing with potentially empty lists or maps.5. Variable Scope Issues:
Example (Illustrating Solution 1):
# Instead of this (which would cause the error):
# output "user_list" {
# value = var.users
# }
# Do this:
locals {
user_list = var.users
}
output "user_list" {
value = local.user_list
}
If you're still encountering the error, please provide the relevant parts of your Terraform code, including variable declarations, the block where the error occurs, and any relevant input values or configurations.
This Terraform code demonstrates best practices for handling variables, outputs, and potential errors. It shows how to correctly use locals for outputs, environment variables for backend configuration, and count for iterating over lists. It also highlights the importance of variable scope when working with modules, ensuring that variables are passed as inputs to be accessible within the module's context.
# Incorrect: Using a variable directly in an output
# output "bucket_name" {
# value = var.bucket_name
# }
# Correct: Using a local to store the variable value
variable "bucket_name" {
type = string
}
locals {
bucket_name = var.bucket_name
}
output "bucket_name" {
value = local.bucket_name
}
# Incorrect: Using a variable in a terraform block
# terraform {
# backend "s3" {
# bucket = var.backend_bucket
# }
# }
# Correct: Using environment variables for backend configuration
# Set TF_VAR_backend_bucket before running Terraform
terraform {
backend "s3" {
bucket = "your-backend-bucket-name" # Replace with actual bucket name
}
}
# Incorrect: Accessing a list element with a potentially invalid index
# variable "servers" {
# type = list(string)
# default = ["server1", "server2"]
# }
# resource "null_resource" "example" {
# provisioner "local-exec" {
# command = "echo ${var.servers[2]}" # Index out of bounds!
# }
# }
# Correct: Handling potential index errors
variable "servers" {
type = list(string)
default = ["server1", "server2"]
}
resource "null_resource" "example" {
count = length(var.servers)
provisioner "local-exec" {
command = "echo ${var.servers[count.index]}"
}
}
# Variable scope issue (demonstrated with modules)
# main.tf
variable "environment" {
default = "dev"
}
module "my_module" {
source = "./module"
}
# module/variables.tf
variable "component_name" {
type = string
}
# module/main.tf
resource "null_resource" "example" {
# Incorrect: Trying to access var.environment directly
# provisioner "local-exec" {
# command = "echo ${var.environment}-${var.component_name}"
# }
# Correct: Passing var.environment as an input to the module
provisioner "local-exec" {
command = "echo ${var.environment}-${var.component_name}"
}
}
Explanation:
Output Example: The corrected code uses a locals
block to store the value of var.bucket_name
. This allows the output to reference the stored value (local.bucket_name
) instead of the variable directly.
Backend Configuration Example: The commented-out section shows the incorrect use of a variable within the terraform
block. The corrected part suggests using environment variables (like TF_VAR_backend_bucket
) as a common way to configure backends.
List Index Example: The first null_resource
block demonstrates the error of accessing a list element with a potentially out-of-bounds index. The corrected version uses count
and count.index
to iterate over the list safely.
Module Example: This highlights how variable scope can lead to errors. The incorrect code in module/main.tf
tries to access var.environment
directly, which is not in scope within the module. The corrected version passes var.environment
as an input variable to the module, making it accessible within the module's scope.
General Understanding:
terraform {}
, resource attribute, etc.) to understand why variables might be restricted there.Troubleshooting Tips:
terraform console
: This interactive tool can be invaluable for debugging variable-related issues. You can experiment with variable references and data structures to see how Terraform evaluates them.Beyond the Basics:
Best Practices:
This table summarizes the common causes of the "Error: Variables not allowed" message in Terraform and provides solutions:
Cause | Problem Description | Solution |
---|---|---|
Variables in Output Values | Trying to directly use an input variable within an output block's value argument. Outputs should reflect values determined after resource creation. |
Store the variable's value in a locals block and reference the local variable in the output. |
Variables in terraform Blocks |
Using variables directly within blocks like terraform { backend {} } . These blocks are evaluated before variable values are known. |
Use command-line flags, environment variables, or separate configuration files (.tfvars ) to provide values for these settings. |
Typos or Incorrect Syntax | A typo in the variable name or an incorrect reference to the variable. | Double-check the variable name (case-sensitive) and ensure you're referencing it correctly (e.g., var.my_variable ). |
Incorrect Data Retrieval (Lists/Maps) | Accessing a non-existent index/key in a list/map or not handling empty collections properly. | Verify the index/key exists and use conditional logic to handle potentially empty lists/maps. |
Variable Scope Issues | Trying to access a variable outside its scope, often when working with modules. | Declare the variable as an input variable for the module and pass it in when calling the module. |
Key Point: Terraform has specific rules about where variables can be used. Understanding these rules is crucial for writing valid Terraform code.
By understanding where variables are and are not allowed in Terraform, you can write more effective and error-free infrastructure code. Remember to use locals for outputs, environment variables or configuration files for backend settings, and be mindful of variable scope, especially with modules. If you encounter the "Error: Variables not allowed" message, carefully review the context of the error, the surrounding code, and the solutions provided in this article to resolve the issue. Clear variable naming, validation, and modularization are valuable practices to further enhance your Terraform code quality and maintainability.