Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for OpenTofu By James Joyner IV · · 8 min read Last reviewed Jul 2026

OpenTofu Error: 'Invalid template interpolation value' Complex Type in String

Quick answer

Fix OpenTofu's 'Invalid template interpolation value' error: stop interpolating a list, map, or object into a string and convert it with jsonencode or join instead.

  • #opentofu
  • #terraform
  • #iac
  • #troubleshooting
  • #errors
Free toolkit

Stuck on this OpenTofu error? Get the free incident triage checklist

A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.

Exact Error Message


│ Error: Invalid template interpolation value

│   on main.tf line 14, in resource "aws_instance" "web":
│   14:   user_data = "servers=${var.server_list}"
│     ├────────────────
│     │ var.server_list is list of string with 3 elements

│ Cannot include the given value in a string template: string required.

The message ends with Cannot include the given value in a string template: string required and the ├── line shows the complex type (here a list of string) you tried to interpolate.

What It Means

String interpolation with ${ ... } produces a string, so the value inside must be convertible to a string. OpenTofu can convert scalars — strings, numbers, and booleans — automatically. It cannot silently convert a collection (list, set, tuple, map, or object) into a string, because there is no single obvious representation. When you place such a complex value inside a "...${...}..." template, OpenTofu refuses with Invalid template interpolation value.

The fix is to decide explicitly how the collection should become text: encode it as JSON, join its elements with a separator, or reference a single scalar element instead of the whole collection.

Common Causes

  • Interpolating a whole list or set into a string, for example "${var.subnets}".
  • Interpolating a map or object where a string was expected.
  • Passing a complex output of one resource into a string field of another without converting it.
  • Building a user_data, tag value, or label from a variable that is a collection rather than a scalar.
  • Forgetting an index or key, so var.tags is used where var.tags["Name"] was intended.

Diagnostic Commands

Reproduce and locate the offending interpolation:

tofu validate

Check the actual type of the value you are interpolating:

tofu console
> type(var.server_list)

Preview how the value would look once encoded as a string:

echo 'jsonencode(["a","b","c"])' | tofu console
# "[\"a\",\"b\",\"c\"]"

Test a join instead, if a delimited string is what you want:

echo 'join(",", ["a","b","c"])' | tofu console
# "a,b,c"

Step-by-Step Resolution

  1. Run tofu validate and read the ├── line to confirm the value’s type. list of string, map of ..., or object(...) all indicate a collection that cannot be interpolated directly.

  2. If you want a JSON representation (common for user_data, IAM policies, or config blobs), wrap the value with jsonencode:

user_data = jsonencode({ servers = var.server_list })
  1. If you want a simple delimited string, use join for lists/sets:
user_data = "servers=${join(",", var.server_list)}"
  1. If you actually meant a single element, add the index or key so the interpolated value is a scalar:
tags = {
  Name = "web-${var.server_list[0]}"
}
  1. For maps or objects, either jsonencode the whole thing or reference one attribute:
labels = jsonencode(var.tags)          # whole map as JSON
env    = "region=${var.tags["region"]}" # single scalar value
  1. Validate and plan to confirm the template now produces a valid string:
tofu validate && tofu plan

Prevention

  • Never interpolate a collection directly; decide up front whether you want JSON (jsonencode) or a delimited string (join).
  • Use type constraints on variables so it is obvious which are scalars and which are collections before you reference them.
  • When a field needs structured data, prefer jsonencode/yamlencode over hand-built strings — they are safe and escape correctly.
  • Test interpolations in tofu console before wiring them into resources, especially for user_data and policy documents.
  • Reference [index] or ["key"] when you only need one element, rather than the whole collection. The prompt library has prompts that generate correct jsonencode/join expressions for common fields.
  • Invalid value for input variable — a variable that fails a type constraint before interpolation is even attempted.
  • Call to unknown function — a typo in jsonencode/join such as jsonencde.
  • Unsuitable value type — a value of the wrong type assigned to a typed argument, outside a template.
  • Invalid index — indexing a collection with a key or position that does not exist.

Frequently Asked Questions

Why can OpenTofu interpolate a number but not a list? Numbers and booleans have a single, unambiguous string form. A list, map, or object could be rendered many ways, so OpenTofu requires you to choose one explicitly with join or jsonencode.

Should I use jsonencode or join? Use jsonencode when the consumer expects structured JSON (user_data scripts, policies, config files). Use join when you just need the elements as one delimited line, such as a,b,c.

Can I interpolate a single element of a list? Yes. var.list[0] or var.map["key"] yields a scalar, which interpolates cleanly. The error only occurs when the whole collection is placed in the template.

Does this apply to heredoc templates too? Yes. The same rule applies inside <<EOT ... EOT heredocs and templatefile() — any ${ ... } must resolve to a string-convertible value.

Where can I find more OpenTofu troubleshooting? See the OpenTofu guides for the full catalog of error walkthroughs.

Free download · 368-page PDF

Fixed it? Get 500 OpenTofu & DevOps AI prompts — free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.

Did this fix your issue?

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.