Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Terraform By James Joyner IV · · 8 min read

Terraform Error: 'Call to function templatefile failed' invalid template syntax

Quick answer

Fix Terraform's templatefile() 'call to function ... failed' error: diagnose undefined variables, bad directive syntax, and literal ${} escaping in the template file, then render it correctly.

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

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Exact Error Message


│ Error: Error in function call

│   on main.tf line 8, in locals:
│    8:   config = templatefile("${path.module}/nginx.conf.tftpl", { port = var.port })

│ Call to function "templatefile" failed:
│ ./nginx.conf.tftpl:12,7-11: Unsupported attribute; This object does not
│ have an attribute named "name".

Other common variants from the same call include a missing variable, a malformed directive, or an unescaped literal:

│ Call to function "templatefile" failed: ./user-data.tftpl:4,15-20:
│ Invalid template interpolation value; The expression result is null.

│ Call to function "templatefile" failed: ./policy.json.tftpl:9,1-4:
│ Unexpected end of template; expecting "endfor" directive.

What It Means

templatefile() reads a file and renders it using the Terraform template language: ${ ... } for interpolation and %{ ... } for directives like for and if. The function only has access to the variables you pass in its second argument (the map), plus Terraform’s built-in functions. It has no access to resource references, var.*, or data.* from the surrounding module.

The error fires when the template references something that is not in the supplied map, uses a mismatched or misspelled directive (%{for} without %{endfor}), or contains a literal ${ that should have been escaped. Because it is evaluated as part of an expression, it stops plan immediately.

Common Causes

  • The template references a key that was not passed in the variables map (${name} when only port was provided).
  • A %{ for } / %{ if } directive is missing its matching %{ endfor } / %{ endif }.
  • A literal ${ or %{ in shell or JSON content that Terraform tries to interpolate instead of treating as text.
  • Passing var.*, path.module, or resource attributes inside the template rather than through the vars map.
  • A null value in the map interpolated into a string that requires a value.
  • Wrong file path or extension so templatefile reads the wrong (or empty) file.

Diagnostic Commands

Reproduce the render in isolation with the console, passing the same variables:

echo 'templatefile("${path.module}/nginx.conf.tftpl", { port = 8080 })' | terraform console

Show the exact template lines the error points to:

sed -n '1,20p' nginx.conf.tftpl

Validate the whole configuration to surface the file/line/column:

terraform validate

List every interpolation and directive the template expects so you can cross-check the vars map:

grep -nE '\$\{|%\{' nginx.conf.tftpl

Step-by-Step Resolution

  1. Read the error’s file:line,col pointer — it names the exact template location and the reason (unsupported attribute, unexpected end, null value).

  2. If a variable is missing, add it to the map. Every ${name} in the template must have a matching key:

locals {
  config = templatefile("${path.module}/nginx.conf.tftpl", {
    port    = var.port
    name    = var.service_name
    upstreams = var.upstreams
  })
}
  1. Fix mismatched directives. Every %{ for x in list } needs a closing %{ endfor }, and every %{ if cond } needs %{ endif }:
%{ for host in upstreams ~}
server ${host}:${port};
%{ endfor ~}
  1. Escape literal ${ or %{ that belong to the output (common in shell heredocs, JSON, or systemd files) by doubling the first character — $${ renders as a literal ${:
export PATH=$${PATH}:/opt/bin
  1. Never reference var.*, path.module, or resources inside the template. Compute those in HCL and pass the results through the map.

  2. Guard against null by supplying defaults in the map (coalesce(var.name, "default")) so no interpolation resolves to null.

  3. Re-run and confirm the render succeeds:

terraform validate && terraform plan

Prevention

  • Keep templates thin: compute values in HCL and pass a complete, explicit vars map.
  • Use the .tftpl extension so editors and reviewers recognize the file as a Terraform template.
  • Always double up $${ and %%{ for literal shell/JSON braces in the output.
  • Test templates with terraform console before wiring them into resources.
  • Provide defaults for optional values so no interpolation can resolve to null.
  • Pair %{ for ~} / %{ endfor ~} and use the ~ whitespace trimmers to keep rendered output clean.
  • Invalid template interpolation value — interpolating a complex type (list/map) directly into a string.
  • Unsupported attribute — the template referenced a key absent from the vars map.
  • Unexpected end of template — a missing endfor/endif directive.
  • Invalid function argument — the file path passed to templatefile does not resolve.

Frequently Asked Questions

Why can’t my template see var.port? templatefile() only exposes the variables in its second argument. Pass { port = var.port } and reference ${port} inside the template.

How do I output a literal ${...} in the rendered file? Escape it by doubling the dollar sign: $${...} renders as ${...}. Use %%{ for a literal %{.

What causes ‘unexpected end of template’? A %{ for } or %{ if } directive without its matching %{ endfor } / %{ endif }. Check the directive pairing.

Can I test a template without applying? Yes — call templatefile(...) inside terraform console with sample variables to render it in isolation. For more templating patterns, see the prompt library.

Why does an interpolation say the result is null? A key in your vars map is null. Provide a default with coalesce() or a fallback value so the interpolation always resolves. More fixes live in the Terraform guides.

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.