Terraform Error: 'Call to function templatefile failed' invalid template syntax
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
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 onlyportwas 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
nullvalue in the map interpolated into a string that requires a value. - Wrong file path or extension so
templatefilereads 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
-
Read the error’s
file:line,colpointer — it names the exact template location and the reason (unsupported attribute, unexpected end, null value). -
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
})
}
- 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 ~}
- 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
-
Never reference
var.*,path.module, or resources inside the template. Compute those in HCL and pass the results through the map. -
Guard against
nullby supplying defaults in the map (coalesce(var.name, "default")) so no interpolation resolves to null. -
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
.tftplextension 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 consolebefore 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.
Related Errors
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 missingendfor/endifdirective.Invalid function argument— the file path passed totemplatefiledoes 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.
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.