Terraform tolist aka tolist() function is a handy tool for converting data into lists. It helps you ensure your configurations are clean and error-free. You can use tolist() to loop through resources or shape outputs. Let’s look at how it works and when to use it.
👉 New to Terraform? Explore our Terraform Variables Guide
👉👉Learn how Terraform map work with tolist()
What is Terraform Tolist and Why It Matters
Terraform supports several primitive data types for variables. It also supports complex data types, which we can categorize as collection and structural types.
- Primitive: string, number, bool
- Complex (Structural) – tuple, object
- Complex (Collection) – list, map
Collection types need to contain elements of the same type, but structural types can contain elements of different types.
The tolist() function in Terraform converts tuples or mixed-type complex types into a proper list of collection type. Tuples and lists can seem similar at first glance. Tuples can be tricky since they’re immutable and don’t work with Terraform’s list-expecting features like for_each or dynamic blocks. tolist() ensures consistency and prevents type-related errors by turning tuples into lists.
Scenario: You’re pulling a tuple of subnet IDs from a module output, but for_each needs a list. This is where tolist() comes into play.
subnet_ids = tolist(module.vpc.private_subnets)
This converts the tuple into a list, letting you loop through it effortlessly. It also allows you to use list functions such as split(), sort(), coalescelist(), chunklist(), distinct(), index() etc..
When to Use Tolist terraform
You’ll want tolist() in scenarios where Terraform expects a list, but you’re stuck with a tuple or mixed data. Here are four common use cases:
- Looping with for_each: Convert module outputs to lists for resource iteration.
- Dynamic Blocks: Ensure nested block configurations handle collections correctly.
- Output Values: Format outputs as lists for cleaner downstream consumption. We already looked at an example of this earlier.
- Accessing Data: Convert values returned by data blocks to lists for consumption in resources.
How does tolist() fit into real Terraform code?
tolist() prevents type mismatches that can halt your terraform apply. It’s especially useful when dealing with module outputs or variables that might not guarantee a list type.
Scenario: You need to deploy your infrastructure in 3 availability zones of a region. You need to use the same configuration when deploying in other regions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
data "aws_availability_zones" "available" { state = "available" } locals { availability_zones_list = tolist(data.aws_availability_zones.available.names) selected_azs = slice(local.availability_zones_list, 0, min(3, length(local.availability_zones_list))) } resource "aws_subnet" "public" { count = length(local.selected_azs) vpc_id = aws_vpc.main.id cidr_block = "10.0.${count.index + 1}.0/24" availability_zone = local.selected_azs[count.index] map_public_ip_on_launch = true tags = { Name = "public-subnet-${count.index + 1}" Type = "public" } } |
In this example, we use tolist() to convert the output of a data block to a list. Once converted, we can use list functions such as slice() to manipulate the list. List elements are indexed. Therefore, we can access the relevant element of the list within our resources by index.
Scenario: You’re using a dynamic block to configure multiple ingress blocks, but the input variable is a set. We use a set as an input variable since ports are identical.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
variable "allowed_ports" { description = "List of allowed ports for web servers" type = set(number) default = [80, 443, 22] } resource "aws_security_group" "web" { name_prefix = "web-sg-" vpc_id = aws_vpc.main.id dynamic "ingress" { for_each = tolist(var.allowed_ports) content { from_port = ingress.value to_port = ingress.value protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] description = "Allow port ${ingress.value}" } } # Other configurations } |
Best Practices: Keep Your Usage Clean
To make the most of tolist(), follow these tips:
- Use with Known Structures: Only apply tolist() when you’re sure the input is a tuple or collection. Random usage can cover up issues that you are supposed to catch.
- Validate Inputs: Pair tolist() with type constraints in variables to catch issues early.
- Don’t Overdo It: If your data is already a list, skip tolist() to keep the code readable.
In the above example, we use tolist() to enforce type.
Why tolist() Belongs in Your Toolkit
Knowing how and when to use tolist() can help you handle issues related to data types in Terraform. It allows you to have more robust Terraform configurations.
Converting tuples to lists unlocks smoother loops, cleaner outputs, and fewer errors. Further, it unlocks a lot of helpful list manipulation functions for your use.
If you require an automated platform to ensure the validity of your Terraform code, consider using ControlMonkey. It assists you in identifying type discrepancies, verifying variable changes, and avoiding configuration mistakes prior to deployment—allowing you to concentrate on developing strong infrastructure rather than troubleshooting data type problems. Request a demo or learn more in our resource library.

FAQs
In Terraform, list is a collection type used to define a sequence of values like [“a”, “b”, “c”]. tolist() is a function used to convert another data structure (like a tuple or set) into a list.
Use tolist() when you’re working with module outputs, dynamic blocks, or data sources that return types incompatible with list-based operations like for_each.
Terraform does not have a built-in list() function.
Instead, list is a type, used to declare variables or outputs that hold an ordered sequence of values.
🧠 Key takeaway:
- list is a type.
- tolist() is a function used for type conversion.