Troubleshoot Terraform Errors: Common Issues และ Solutions

ทุกทีมที่ใช้ Terraform จัดการ infrastructure ต้องเคยพบ error ทั้ง runtime, planning, และ state — การรู้จัก error message ที่พบบ่อยพร้อมวิธีวิเคราะห์และแก้ไขช่วยลดเวลาค้นคว้าลงมาก โดยเฉพาะใน CI/CD pipeline ที่ pipeline ล้มเหลวตอนดึก

บทความนี้รวม error pattern หลักที่ทีม DevOps เจอบ่อย พร้อมสาเหตุและคำสั่งสำหรับแก้ไข โดยจัดกลุ่มตาม phase ที่ error ปรากฏ ได้แก่ init, plan, apply และ state management

Error ช่วง Init

Failed to query available provider packages

Error: Failed to query available provider packages
Could not retrieve the list of available versions for provider hashicorp/aws:
no available releases match the given constraints >= 5.0, < 4.0

สาเหตุ — version constraint ใน required_providers ขัดแย้งกันเอง หรือระบุ range ที่ไม่มี release อยู่จริง ให้ตรวจสอบบล็อก required_providers ของ root module และทุก module ที่ใช้งาน

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

Inconsistent dependency lock file

Error: Inconsistent dependency lock file
The following dependency selections recorded in the lock file are inconsistent
with the current configuration

เกิดจาก .terraform.lock.hcl ระบุ version ที่ไม่ตรงกับ configuration ใหม่ แก้ด้วย terraform init -upgrade เพื่อให้ lock file อัพเดต หรือ terraform providers lock เพื่อเพิ่ม platform hash สำหรับ OS อื่น

terraform init -upgrade
terraform providers lock -platform=linux_amd64 -platform=darwin_arm64

Backend initialization required

Error: Backend initialization required, please run "terraform init"
Reason: Initial configuration of the requested backend "s3"

เปลี่ยน backend config แล้วยังไม่ได้ init ใหม่ หรือเพิ่งเพิ่ม backend ใหม่ ให้รัน terraform init -reconfigure — ระวัง flag นี้จะไม่ migrate state เก่า ถ้าต้องการย้าย state ให้ใช้ -migrate-state แทน

Error ช่วง Plan

Reference to undeclared resource

Error: Reference to undeclared resource
on main.tf line 42, in resource "aws_instance" "web":
  42:   subnet_id = aws_subnet.public.id

A managed resource "aws_subnet" "public" has not been declared in the root module.

เกิดเมื่ออ้างอิง resource ชื่อผิด หรือ resource อยู่ใน module แต่เรียกแบบไม่ผ่าน module.<name> — ตรวจว่า resource address ตรงกับที่ประกาศจริง กรณีอยู่ใน module ต้องเรียกเป็น module.vpc.subnet_id โดย module นั้นต้อง output ค่าออกมาก่อน

Invalid for_each argument

Error: Invalid for_each argument
The "for_each" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.

เกิดเมื่อค่าที่ส่งให้ for_each เป็น computed value (เช่น id ของ resource ที่ยังไม่สร้าง) — แก้ด้วยการ refactor ให้ใช้ค่าที่รู้ก่อน plan เช่น ใช้ variable, locals หรือ static set

# ❌ พัง — depends on computed attribute
resource "aws_instance" "web" {
  for_each = toset(aws_subnet.public[*].id)
  # ...
}

# ✅ ใช้ชื่อ subnet ที่รู้ล่วงหน้า
resource "aws_instance" "web" {
  for_each = toset(["public-a", "public-b", "public-c"])
  subnet_id = aws_subnet.public[each.key].id
}

Cycle detected

Error: Cycle: aws_security_group.web, aws_security_group.db

resource สอง resource อ้างถึงกันและกัน Terraform ไม่สามารถจัดลำดับสร้างได้ แก้ด้วย aws_security_group_rule แยกจาก security group หลัก เพื่อยกออกจาก dependency graph

resource "aws_security_group" "web" { vpc_id = var.vpc_id }
resource "aws_security_group" "db"  { vpc_id = var.vpc_id }

resource "aws_security_group_rule" "web_to_db" {
  type                     = "ingress"
  from_port                = 3306
  to_port                  = 3306
  protocol                 = "tcp"
  source_security_group_id = aws_security_group.web.id
  security_group_id        = aws_security_group.db.id
}

Error ช่วง Apply

Error: Resource already exists

Error: creating S3 Bucket (my-bucket): BucketAlreadyOwnedByYou:
Your previous request to create the named bucket succeeded and you already own it

resource ชื่อเดียวกันมีอยู่ใน cloud แล้ว แต่ไม่อยู่ใน state — เกิดเมื่อถูกสร้างมือหรือ state หาย แก้ด้วย terraform import เพื่อ reconcile state กับของจริง

terraform import aws_s3_bucket.logs my-bucket
terraform plan  # ตรวจสอบ drift ก่อน apply

Error: InvalidParameterValue / ValidationError

Error: InvalidParameterValue: Value (t3.nano) for parameter instanceType is invalid.
Instance type t3.nano does not exist in availability zone ap-southeast-1c

cloud provider ปฏิเสธค่าที่ส่งไป — ต้องตรวจกับ AWS CLI ว่า AZ ใดรองรับ instance type ใด

aws ec2 describe-instance-type-offerings \
  --location-type availability-zone \
  --filters Name=instance-type,Values=t3.nano \
  --region ap-southeast-1

Timeout / Context deadline exceeded

Error: waiting for RDS DB Instance (prod-db) to be available:
timeout while waiting for state to become 'available'

resource ใช้เวลาสร้างนานกว่า default timeout — เพิ่ม timeout block ใน resource

resource "aws_db_instance" "main" {
  # ...
  timeouts {
    create = "60m"
    update = "80m"
    delete = "60m"
  }
}

Throttling / RequestLimitExceeded

API rate limit ของ cloud provider — ลด -parallelism จาก default 10 ลงเหลือ 5 หรือใช้ retry config ใน provider

terraform apply -parallelism=5

# หรือตั้งใน provider
provider "aws" {
  max_retries = 10
  retry_mode  = "adaptive"
}

Error เกี่ยวกับ State

State lock timeout

Error: Error acquiring the state lock
Lock Info:
  ID:        abc-123-def
  Operation: OperationTypeApply
  Who:       user@host
  Created:   2026-03-01 10:15:00 UTC

มี run ค้างอยู่ หรือ crash ก่อนปลด lock — ตรวจว่าไม่มี process อื่นรันจริง ๆ ก่อน force-unlock เพราะ lock มีไว้ป้องกัน state corrupt

terraform force-unlock abc-123-def

State file drift

Note: Objects have changed outside of Terraform
Terraform detected the following changes made outside of Terraform since the last "terraform apply"

มีการแก้ cloud resource นอกระบบ (manual change, ระบบอื่น) — ตรวจสอบก่อนว่าการเปลี่ยนแปลงนั้น intentional หรือไม่ ถ้าเป็น intentional ให้ update code ให้ตรงกัน หรือใช้ lifecycle { ignore_changes = [tag] } หากเป็น field ที่ cloud จัดการเอง

State schema version mismatch

Error: state snapshot was created by Terraform v1.8.0, which is newer than current v1.6.2

state file สร้างด้วย version ที่ใหม่กว่า binary ปัจจุบัน — อัพเกรด binary ให้เท่าหรือใหม่กว่า version ที่สร้าง state

Module source change without init

Error: Module not installed
This module is not yet installed. Run "terraform init" to install all modules required by this configuration.

เปลี่ยน source หรือ version ของ module แต่ยังไม่ได้ init — รัน terraform init -upgrade เพื่อ download ใหม่

Error เกี่ยวกับ Authentication

NoCredentialsError / UnauthorizedOperation

Error: NoCredentialProviders: no valid providers in chain
UnauthorizedOperation: You are not authorized to perform this operation

ไม่พบ credential หรือ credential ไม่มี permission — ตรวจ environment variable, shared credentials file, และ IAM policy ของ role/user ที่ใช้

# ตรวจว่ารู้ identity ปัจจุบัน
aws sts get-caller-identity

# ตรวจ credentials chain
echo $AWS_ACCESS_KEY_ID
cat ~/.aws/credentials

Expired token

ใช้ STS session token ที่หมดอายุ — ต่ออายุ session ใหม่ก่อน run

aws sso login
# หรือ
aws sts get-session-token --duration-seconds 3600

กลยุทธ์การแก้ Error ทั่วไป

  • เปิด verbose logTF_LOG=DEBUG terraform apply 2> debug.log ดูว่า error เกิดจาก provider หรือ core
  • ลอง plan แยก resource-target=aws_instance.web เพื่อ isolate ปัญหา (ใช้ชั่วคราวเท่านั้น)
  • ตรวจ provider version — บาง bug แก้แล้วใน minor release ให้ดู CHANGELOG ของ provider
  • ล้าง cacherm -rf .terraform แล้ว init ใหม่ หาก lock file หรือ plugin binary เสียหาย
  • ใช้ terraform validate — ตรวจ syntax ก่อน plan ลด error ที่เจอสาย apply
  • อ่าน HashiCorp documentation — error message มักมี link ไปหน้า troubleshooting ที่เกี่ยวข้อง

การป้องกัน Error ก่อนเกิด

  • ตั้ง pre-commit hook รัน terraform fmt, terraform validate, tflint ก่อน commit
  • ใช้ terraform plan -out=tfplan ใน CI ก่อน apply เสมอ ไม่ plan+apply ในคำสั่งเดียว
  • จำกัดสิทธิ์ service account ให้เฉพาะที่จำเป็น (least privilege) — ทำให้ error ชัดเจนว่าขาด permission อะไร
  • ตั้ง alert บน state file modification ผ่าน S3 event / CloudTrail เพื่อจับการแก้ไข state ผิดปกติ
  • Backup state file อัตโนมัติด้วย S3 versioning + lifecycle policy

สรุป

การ troubleshoot error ของโครงสร้างพื้นฐานเป็นทักษะสำคัญของ DevOps engineer — การรู้จัก error message ที่พบบ่อยและวิธีวิเคราะห์ช่วยให้แก้ปัญหาได้เร็วกว่าการเดา ทั้งยังลดโอกาสที่ state หรือ cloud resource จะหลุดจาก control ของทีม

หลักสำคัญคือ อ่าน error message ให้ครบทุกบรรทัด เปิด verbose log เมื่อข้อความไม่ชัด และแยกปัญหาเป็น phase (init, plan, apply, state) เพื่อจำกัดขอบเขตการวิเคราะห์ — วิธีนี้ทำให้แม้ระบบ infrastructure จะซับซ้อนแค่ไหน ก็ยังสามารถ pinpoint root cause ได้อย่างเป็นระบบ