Terraformよくあるエラー集 — エラーメッセージ別の原因と解決策

1. 概要

Terraformで遭遇しやすいエラーメッセージの原因と解決方法をまとめました。エラーメッセージをそのまま検索してこのページに来た方は、該当セクションを参照してください。


2. 変数・式のエラー

Error: Inconsistent conditional result types

│ Error: Inconsistent conditional result types
│
│   on main.tf line 5, in resource "aws_instance" "web":
│    5:   instance_type = var.environment == "prd" ? "t3.medium" : 0
│
│ The true and false result expressions must have consistent types. The
│ given expressions are string and number, respectively.

原因: 三項演算子の「trueの値」と「falseの値」の型が違う(片方がstring、もう片方がnumberなど)。

解決方法: 両方の値の型を揃える。

# ❌ string と number で型不一致
instance_type = var.environment == "prd" ? "t3.medium" : 0

# ✅ 両方 string に揃える
instance_type = var.environment == "prd" ? "t3.medium" : "t3.micro"

# ✅ nullを返したい場合はtostring()等で型を明示
volume_size = var.enable_extra_disk ? 100 : null
# ↑ nullとnumberは型一致しないため、tostring(null)などで対処するか
# 条件式の代わりにlookup/tryを使う

Error: Variables not allowed

│ Error: Variables not allowed
│
│   on main.tf line 8, in terraform:
│    8:     bucket = var.state_bucket
│
│ Variables may not be used here.

原因: backendブロック内でvar.local.を使おうとした。backendブロックは初期化時に評価されるため、変数を参照できない。

解決方法: -backend-configオプションで外部から渡す。

# -backend-config オプションで値を渡す
terraform init \
  -backend-config="bucket=myproject-terraform-state" \
  -backend-config="key=prod/terraform.tfstate"

詳細は「backendの設定方法」を参照。


Error: Invalid value for input variable

│ Error: Invalid value for input variable
│
│   on terraform.tfvars line 1:
│    1: environment = "staging"
│
│ The argument "environment" value "staging" is invalid: environment は
│ dev/stg/prd のいずれかを指定してください。

原因: variableブロックにvalidationが設定されており、渡した値がルールを満たさない。

解決方法: 許可された値を確認して正しい値を渡す。

# variableのvalidationを確認
variable "environment" {
  type = string
  validation {
    condition     = contains(["dev", "stg", "prd"], var.environment)
    error_message = "environmentはdev/stg/prdのいずれかを指定してください。"
  }
}

# → "staging" ではなく "stg" を渡す必要がある

3. count / for_each のエラー

Error: Invalid count argument

│ Error: Invalid count argument
│
│   on main.tf line 3, in resource "aws_instance" "web":
│    3:   count = aws_security_group.main.id
│
│ The "count" value depends on resource attributes that cannot be
│ determined until apply, so Terraform cannot predict how many instances
│ will be created.

原因: countに、apply後にしか決まらないリソース属性(IDなど)を使っている。

解決方法: countにはapply前に値が確定する式(変数・数値など)だけを使う。

# ❌ リソースのIDは apply 後にしか決まらない
count = length(aws_security_group.main.id)

# ✅ 変数や固定値を使う
count = var.enable_web ? 1 : 0
count = length(var.server_names)

Error: The for_each value depends on resource attributes that cannot be determined until apply

│ Error: Invalid for_each argument
│
│   on main.tf line 3, in resource "aws_instance" "web":
│    3:   for_each = aws_subnet.main
│
│ 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に、apply後にしか決まらないリソース属性を直接渡している。

解決方法: for式でキーが確定している値だけを使ったmapに変換する。

# ❌ apply後にしか決まるsensitive属性を含む場合にエラー
for_each = aws_subnet.main

# ✅ キーが確定している変数から生成する
for_each = var.subnet_configs  # 変数から生成
for_each = local.subnets_map   # 変数やdata sourceからlocalsで事前に変換しておく

Error: for_each requires a map or set of strings

│ Error: Invalid for_each argument
│
│   on main.tf line 3, in resource "aws_s3_bucket" "logs":
│    3:   for_each = var.bucket_names
│
│ The given "for_each" argument value is unsuitable: the "for_each" argument
│ must be a map, or set of strings, and you have provided a value of type
│ tuple.

原因: for_eachlistを直接渡した。for_eachmapset(string)のみ受け付ける。

解決方法: toset()でset型に変換するか、for式でmapに変換する。

# ❌ list は直接渡せない
for_each = var.bucket_names        # list(string) → エラー
for_each = ["access", "error"]     # tuple → エラー

# ✅ toset()でset(string)に変換
for_each = toset(var.bucket_names)
for_each = toset(["access", "error"])

# ✅ for式でmapに変換
for_each = { for name in var.bucket_names : name => name }

詳細は「for_eachの使い方」「toset/tolist/tomapの使い方」を参照。


4. 依存関係・構造のエラー

Error: Cycle detected

│ Error: Cycle: aws_instance.web, aws_security_group.main
│
│ Terraform detected a cycle in the dependency graph between these
│ resources. Please resolve the cycle to continue.

原因: リソースAがリソースBを参照し、リソースBもリソースAを参照している(循環依存)。

解決方法: 循環している参照をどちらか一方から取り除く。参照式ではなくdepends_onを使っている場合は不要なdepends_onを削除する。

# ❌ 循環依存の例
resource "aws_security_group" "app" {
  egress {
    security_groups = [aws_security_group.db.id]  # dbを参照
  }
}

resource "aws_security_group" "db" {
  ingress {
    security_groups = [aws_security_group.app.id]  # appを参照(循環!)
  }
}

# ✅ 解決: セキュリティグループルールを分離する(aws_security_group_rule を使う)
resource "aws_security_group_rule" "db_from_app" {
  type                     = "ingress"
  security_group_id        = aws_security_group.db.id
  source_security_group_id = aws_security_group.app.id
  protocol                 = "tcp"
  from_port                = 5432
  to_port                  = 5432
}

Error: Missing required argument

│ Error: Missing required argument
│
│   on main.tf line 10, in resource "aws_instance" "web":
│   10: resource "aws_instance" "web" {
│
│ The argument "ami" is required, but no definition was found.

原因: リソースに必須の引数が指定されていない。

解決方法: プロバイダーの公式ドキュメントで必須引数を確認する。

# ✅ aws_instance の必須引数を確認して追加
resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux_2023.id  # ← 必須
  instance_type = "t3.micro"                          # ← 必須

  tags = {
    Name      = "web"
    ManagedBy = "terraform"
  }
}

Error: Unsupported argument

│ Error: Unsupported argument
│
│   on main.tf line 5, in resource "aws_instance" "web":
│    5:   instance_count = 3
│
│ An argument named "instance_count" is not expected here.

原因: 存在しない引数名を書いている(タイポ、または古いバージョンの引数名)。

解決方法: 公式ドキュメントで正しい引数名を確認する。countはリソースのプロパティではなくメタ引数。

# ❌ 存在しない引数
instance_count = 3

# ✅ countはメタ引数(同じインデントレベルに書く)
resource "aws_instance" "web" {
  count = 3  # メタ引数

  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"
}

5. state・backendのエラー

Error: Error acquiring the state lock

│ Error: Error acquiring the state lock
│
│ Lock Info:
│   ID:        a1b2c3d4-e5f6-...
│   Path:      myproject-state/prod/terraform.tfstate
│   Operation: OperationTypeApply
│   Who:       alice@example.com
│   Created:   2026-01-15 10:30:00 +0000 UTC

原因1(正常): 別の人またはCIがterraform applyを実行中。

対処: 実行完了まで待つ。完了すればロックは自動解除される。

原因2(異常): 前回の実行が異常終了してロックが残留している。

対処: チームに確認してからforce-unlockで解除する。

# Lock Info の ID を使って強制解除(チームへの確認必須)
terraform force-unlock a1b2c3d4-e5f6-...

⚠️ 警告: force-unlockは他のユーザーのapplyを強制終了させる危険があります。必ずチームに確認してから実行してください。


Error: Backend configuration changed

│ Error: Backend configuration changed
│
│ A change in the backend configuration has been detected, which may
│ require migrating existing state.

原因: backendブロックの設定を変更したのにterraform initを再実行していない。

解決方法:

# Stateは移行せず再設定(バックエンドのURLが変わったが移行不要な場合)
terraform init -reconfigure

# 既存StateをS3等の新しいバックエンドに移行する場合
terraform init -migrate-state

Error: state data in S3 does not have the expected content

│ Error: Error loading state: state data in S3 does not have the expected
│ content. This may be caused by a previous force-unlock.

原因: State Lockの強制解除後にStateファイルが破損している、または複数のapplyが同時に走ってStateが上書きされた。

対処: S3のバージョニングが有効な場合、S3コンソールから以前のバージョンに戻す。バックアップがない場合はterraform importで手動復元が必要。


6. initのエラー

Error: Failed to install provider

│ Error: Failed to install provider
│
│ Error while installing hashicorp/aws v5.50.0: could not query provider
│ registry for registry.terraform.io/hashicorp/aws

原因: ネットワーク接続の問題(プロキシ環境、オフライン環境など)、または.terraform.lock.hclrequired_providersのバージョン制約が競合している。

解決方法:

# .terraform/ と .terraform.lock.hcl を削除してやり直す
rm -rf .terraform
rm .terraform.lock.hcl
terraform init

# プロキシ経由の場合は環境変数を設定
export HTTPS_PROXY=http://proxy.example.com:8080
terraform init

Error: Provider version requirements conflict

│ Error: Failed to query available provider packages
│
│ Could not retrieve the list of available versions for provider
│ hashicorp/aws: locked provider registry.terraform.io/hashicorp/aws
│ 5.0.0 does not match configured version constraint ~> 5.50.

原因: .terraform.lock.hclに記録されたバージョンと、required_providersの制約が合わない。

解決方法:

# ロックファイルを更新してプロバイダーをアップグレード
terraform init -upgrade

7. planの意図しない挙動

-/+(置換)が意図せず発生する

  # aws_instance.web must be replaced
-/+ resource "aws_instance" "web" {
      ~ id = "i-0abc123" -> (known after apply)
    + ami = "ami-newvalue"  # forces replacement

原因: AMI IDを変更した、instance_typeを変更した、など「変更すると再作成が必要」な属性を変更した。

確認: 変更前に必ずterraform planforces replacementの記載を確認する。

対処(ダウンタイムを避けたい場合):

lifecycle {
  create_before_destroy = true  # 先に新規インスタンスを作ってから古いものを削除
}

No changesなのにapplyで変更が発生する

原因: Terraform Provider側のバグ(apply後にState値がAPIレスポンスで上書きされる)、またはignore_changesplan時にのみ有効でapply後に差分が生じるケース。

対処:

lifecycle {
  ignore_changes = [tags]  # 外部から変更されるタグを無視
}

8. 関連記事

エラー個別詳解(Phase 3)


9. まとめ

このページでカバーしているエラーの早見表:

エラー主な原因
Inconsistent conditional result types三項演算子の型不一致
Variables not allowedbackendブロック内でvar.を使用
Invalid value for input variablevalidationルール違反
Invalid count argumentapplyまで不明な値をcountに使用
for_each set以外listをfor_eachに直接渡した
Cycle detected循環依存
Missing required argument必須引数の未設定
Error acquiring the state lockState Lockの競合または残留
Backend configuration changedbackend変更後のinit未実施
Failed to install providerネットワーク・バージョン制約の問題

動作確認バージョン: Terraform >= 1.9 / AWS Provider ~> 5.0 公式ドキュメント: https://developer.hashicorp.com/terraform/language/expressions