The "template not found" error occurs when Terraform cannot locate a template file referenced in your configuration. This typically happens due to incorrect file paths, missing interpolation syntax, or file location mismatches in CI/CD environments. Fix it by verifying paths use `${path.module}` interpolation and files exist before Terraform runs.
When using the `templatefile()` function or the deprecated `template_file` data source in Terraform, the template file must exist on disk before Terraform executes. This error means Terraform searched for the file at the specified path but couldn't find it. The most common cause is using literal path strings without proper interpolation. For example, writing `file("path.module/templates/init.tpl")` will search for a file literally named "path.module" in your current directory, rather than interpolating `path.module` to the actual module path. Terraform requires the `${path.module}` syntax to resolve paths relative to the module location.
First, confirm the template file actually exists at the path you've specified:
# For example, if using path.module/templates/init.tpl
ls -la /path/to/your/module/templates/init.tpl
# Or from the module directory
ls -la templates/init.tplIf the file doesn't exist, create it with the appropriate content. Terraform cannot render a template from a file that doesn't exist - the file must be present before you run terraform plan or terraform apply.
The most common cause is forgetting to use interpolation syntax. Update your Terraform code:
Incorrect (will fail):
resource "aws_instance" "example" {
user_data = templatefile("path.module/templates/init.tpl", {
region = var.aws_region
})
}Correct:
resource "aws_instance" "example" {
user_data = templatefile("${path.module}/templates/init.tpl", {
region = var.aws_region
})
}The key difference is using ${path.module} with the dollar sign and curly braces. This tells Terraform to interpolate the actual module path instead of treating it as a literal string.
When running Terraform, ensure your working directory is correct:
# Show current directory
pwd
# List files to verify template exists relative to current directory
ls -la templates/
# If templates are in a subdirectory, adjust your path accordingly
ls -la ./path/to/templates/If using Terraform modules, remember that path.module always refers to the directory where the .tf file is located, not your current working directory. This is especially important in CI/CD pipelines where working directories may vary.
If your error only happens in CI/CD but works locally, the issue is likely that template files aren't being transferred to the CI/CD environment:
# Example GitHub Actions - ensure all template files are included
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: terraform-config
path: |
*.tf
templates/
modules/
# Or ensure they're checked out:
- name: Checkout code
uses: actions/checkout@v3For GitLab CI, Terraform Cloud, or other platforms, ensure your configuration includes all necessary files in the artifact or working directory before running Terraform.
While not required, using the .tftpl extension (Terraform Template) is a best practice:
# Rename your template file
mv templates/init.tpl templates/init.tftplThen update your Terraform code:
user_data = templatefile("${path.module}/templates/init.tftpl", {
region = var.aws_region
})This helps editors provide syntax highlighting and better error detection for template files.
If you're using local_file with rendered templates, use the correct attribute:
resource "local_file" "config" {
# Use 'content' for rendered template content
content = templatefile("${path.module}/templates/config.tftpl", {
app_name = var.app_name
})
filename = "${path.module}/generated/config.ini"
}
# NOT 'source' - that expects a file path, not rendered content
# source = "${path.module}/templates/config.tftpl" # Wrong!The source attribute reads a literal file, while content accepts the rendered output from templatefile().
Why `path.module` is essential: Terraform modules can be called from anywhere in your configuration, and the module location may differ from your working directory. Using path.module ensures template files are always found relative to the module file itself, not the directory where you run terraform. This is critical for reusable, portable modules.
Deprecated template_file data source: The template_file data source from the hashicorp/template provider is deprecated in favor of the built-in templatefile() function. If you're using the old provider, migration is simple - just replace data.template_file.example.rendered with templatefile(...) calls.
VSCode false positives: The Terraform extension in VSCode may report "templatefile() failed: no file exists" even when the file does exist and Terraform applies successfully. This is a parsing limitation of the extension, not an actual Terraform error. Always verify with terraform plan before trusting the editor warning.
Cross-platform path syntax: Terraform uses forward slashes (/) for paths across all platforms, including Windows. Never use backslashes in Terraform code, even on Windows systems.
Files must exist at plan time: Unlike local_file resources which can be created during apply, the files referenced by templatefile() must exist before Terraform begins planning. You cannot use depends_on to defer checking until after another resource creates the file.
Error: Error generating private key
How to fix 'Error generating private key' in Terraform
Error creating Kubernetes Service: field is immutable
How to fix "field is immutable" errors in Terraform
Error: Error creating local file: open: permission denied
How to fix "Error creating local file: permission denied" in Terraform
Error: line endings have changed from CRLF to LF
Line endings have changed from CRLF to LF in Terraform
Error: Error making HTTP request: 500 Internal Server Error
HTTP 500 Internal Server Error in Terraform