Cách khắc phục lỗi 'Invalid template interpolation value' trong Terraform

Mới bắt đầu🏗️ Terraform2026-06-07| Terraform CLI (v0.12+), Linux, macOS, hoặc Windows

Error Message

Error: Invalid template interpolation value: the template interpolation at line X requires a string value, not object.
#terraform#devops#hcl#khắc phục sự cố

Vấn đề

Terraform thường khá thông minh về kiểu dữ liệu, nhưng nó rất khắt khe với việc nội suy chuỗi (string interpolation). Bạn có thể gặp lỗi này trong quá trình plan hoặc apply khi cố gắng đưa một cấu trúc dữ liệu phức tạp vào vị trí yêu cầu một chuỗi đơn giản:

Error: Invalid template interpolation value

on main.tf line 42, in resource "aws_instance" "example":
42:   user_data = "echo ${var.config_map}"

|----------------
| var.config_map là một object với 2 thuộc tính

Không thể đưa giá trị đã cho vào template chuỗi: yêu cầu kiểu string.

Cú pháp ${...} chỉ có một nhiệm vụ duy nhất: chèn các chuỗi. Nếu bạn truyền cho nó một list, map hoặc object, Terraform sẽ không tự đoán cách định dạng chúng. Nó mong đợi một chuỗi phẳng (flat string), và khi nhận được một object nhiều lớp, quá trình sẽ dừng lại.

Các trường hợp phổ biến

Đây không chỉ là lỗi cú pháp đơn thuần; đó là sự không khớp về kiểu dữ liệu. Bạn sẽ thường xuyên gặp lỗi này khi:

  • Truyền một map chứa các biến môi trường vào script shell user_data.
  • Cố gắng in một danh sách gồm 5 địa chỉ IP riêng vào một file cấu hình.
  • Chèn toàn bộ một resource object vào một tag hoặc trường metadata.

Ba cách để khắc phục

Giải pháp tùy thuộc vào việc bạn muốn dữ liệu trông như thế nào sau khi chuyển đổi. Dưới đây là các phương pháp chuẩn.

1. Sử dụng jsonencode() cho Map và Object

Nếu đích đến của bạn (như một tham số SSM hoặc file cấu hình) yêu cầu dữ liệu có cấu trúc, hãy sử dụng jsonencode(). Hàm này sẽ tự động chuyển đổi HCL object của bạn thành một chuỗi JSON hợp lệ.

Cách làm sai:

resource "aws_ssm_parameter" "config" {
  name  = "app_settings"
  type  = "String"
  value = "settings = ${var.my_map}" # Dòng này sẽ gây ra lỗi
}

Cách làm đúng:

resource "aws_ssm_parameter" "config" {
  name  = "app_settings"
  type  = "String"
  value = jsonencode(var.my_map) # Trả về "{\"key\":\"value\"}"
}

2. Sử dụng join() cho List

Làm việc với List có chút phức tạp hơn. Nếu bạn có một danh sách các chuỗi, thông thường bạn sẽ muốn gộp chúng lại với nhau bằng một ký tự phân cách như dấu phẩy hoặc khoảng trắng.

Ví dụ:

resource "aws_instance" "web" {
  # Gộp danh sách 3 khối CIDR thành một chuỗi duy nhất cách nhau bởi dấu phẩy
  user_data = <<-EOT
    #!/bin/bash
    echo "Nguồn được phép: ${join(", ", var.external_ips)}"
  EOT
}

3. Sử dụng HCL Directive cho định dạng phức tạp

Đôi khi jsonencode tạo ra kết quả quá lộn xộn. Nếu bạn đang sử dụng templatefile() để tạo cấu hình tùy chỉnh (như cấu hình Nginx hoặc HaProxy), hãy sử dụng chỉ thị vòng lặp for ngay bên trong template.

Template của bạn (config.tftpl):

%{ for name, ip in servers ~}
server ${name} ${ip}:8080
%{ endfor ~}

Mã Terraform của bạn:

content = templatefile("config.tftpl", { 
  servers = { "web01" = "10.0.1.5", "web02" = "10.0.1.6" }
})

Kiểm tra mà không cần deploy

Đừng đợi lệnh terraform plan chậm chạp để xem bản sửa lỗi của bạn có hoạt động hay không. Hãy sử dụng console tích hợp để nhận phản hồi tức thì:

  • Chạy terraform console trong terminal của bạn.
  • Nhập logic của bạn: join(" | ", ["prod", "staging"]).
  • Nếu nó xuất ra "prod | staging", phần nội suy của bạn đã an toàn.

Mẹo từ chuyên gia

  • Khai báo kiểu dữ liệu chặt chẽ: Định nghĩa các biến của bạn một cách rõ ràng. Sử dụng type = map(string) giúp bắt lỗi ngay từ giai đoạn nhập liệu thay vì thất bại giữa chừng khi đang deploy.
  • Hỗ trợ YAML: Nếu JSON quá cồng kềnh cho log của bạn, yamlencode() hoạt động hoàn toàn giống như JSON nhưng xuất ra định dạng YAML sạch sẽ hơn.
  • Bảo mật: Cẩn thận khi dùng jsonencode trên các object chứa bí mật (secrets). Nếu một biến được đánh dấu sensitive = true, Terraform sẽ ẩn toàn bộ chuỗi trong đầu ra CLI để giữ an toàn cho mật khẩu.

Related Error Notes