The Problem: Everything Looks Right, But It Fails
Youβve just finished a complex Terraform module to deploy a cluster of 3 EC2 instances. Youβre using the templatefile() function to inject dynamic environment variables into a shell script. In your IDE, everything looks perfect. The user_data.tpl file is sitting right there in the templates folder where it belongs.
You run terraform plan and hit a wall:
Error: Error in function call
Call to function "templatefile" failed: open ./templates/user_data.tpl: no such file or directory.
You might even run ls ./templates/user_data.tpl from your terminal and see the file listed. So why is Terraform refusing to see it? The issue isn't that the file is missing. The issue is that Terraform is looking in the wrong place.
Why Your Paths Are Breaking
Terraform resolves relative paths like ./templates/user_data.tpl based on your current working directory. This is the folder where you execute the terraform command, not the folder where your .tf code actually lives.
Imagine your project structure looks like this:
.
βββ main.tf (Root configuration)
βββ modules/
βββ web_server/
βββ main.tf (Module code)
βββ templates/
βββ user_data.tpl
If you call templatefile("./templates/user_data.tpl", {}) inside modules/web_server/main.tf, Terraform searches for that file starting from the root directory. Since the file is buried inside the module folder, the search fails. This context shift is the #1 cause of pathing errors in CI/CD pipelines like GitHub Actions or Jenkins.
First Checks
Before changing your code, rule out the simple mistakes that trip up even senior engineers:
- Case Sensitivity: On a Linux-based CI runner,
Templates/andtemplates/are different folders. - Hidden Extensions: Ensure your file isn't actually named
user_data.tpl.txt. - Execution Context: Are you running Terraform from a subfolder using the
-chdirflag? This changes where Terraform looks for relative paths.
The Reliable Solution: Use path.module
To make your code portable, you need to tell Terraform to look for the file relative to the module itself. Terraform provides a built-in variable called path.module for exactly this purpose. This variable always points to the filesystem path of the directory containing the .tf file where it is used.
Update your resource block like this:
# The Reliable Approach
resource "aws_instance" "web" {
count = 3
# ...
user_data = templatefile("${path.module}/templates/user_data.tpl", {
admin_email = var.admin_email
server_id = count.index
})
}
When you use ${path.module}, Terraform generates an absolute path. It won't matter if you run the plan from the root, a subfolder, or a remote build agent. The path will always be correct.
Other Useful Path Variables
path.root: Points to the directory where you initiated the Terraform run.path.cwd: Points to your current terminal directory.
For templatefile calls inside modules, path.module is almost always the right tool for the job.
Debug Faster with Terraform Console
Don't wait 60 seconds for a full terraform plan just to test a path. You can verify your logic instantly using the terraform console. This is the fastest way to debug pathing issues without actually deploying anything.
- Open your terminal in your project root.
- Run
terraform console. - Test the absolute path by typing:
abspath("${path.module}/modules/web_server/templates/user_data.tpl") - Try reading the file content directly:
file("${path.module}/modules/web_server/templates/user_data.tpl")
If the file() function returns your script content without an error, your path is fixed. Press Ctrl+C to exit and move on with your deployment.
Wrapping Up
The "no such file or directory" error is rarely about a missing file. It's almost always a misunderstanding of how Terraform handles execution context. By moving away from hardcoded relative paths and embracing ${path.module}, you make your infrastructure code resilient, portable, and much easier to debug.

