Terraformエラーの解決方法: 'count' の値がリソースの属性に依存している場合

intermediate🏗️ Terraform2026-03-30| Terraform CLI (全バージョン), AWS/Azure/GCP プロバイダー

Error Message

The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created.
#count#for_each#plan#dynamic-value#terraform

エラーのシナリオあるリソースが別のリソースの出力に依存するようなインフラを構築しているとします。例えば、一連のサブネットを作成し、作成された各サブネットに対してEC2インスタンスを起動しようとする場合です。コードの論理は正しく見えますが、terraform planを実行すると、次のような壁にぶつかります。

Error: Invalid count argument

on main.tf line 24, in resource "aws_instance" "web":
24:   count = length(aws_subnet.public_subnets[*].id)

The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created.

発生原因Terraformは明確に分かれたフェーズで動作します。Planフェーズでは、Terraformは依存関係グラフを構築し、作成、更新、または削除が必要なリソースの数を正確に計算します。これを行うには、countまたはfor_eachに渡されるすべての値が、実際にインフラが操作されるに確定している必要があります。

このエラーは、リソース作成後にのみ存在する属性(生成されたID、計算されたARN、まだ存在しないリソースからのIDリストなど)をcountに指定したときに発生します。applyが完了するまで何個のIDが返されるかTerraformは予測できないため、処理を拒否します。

解決方法構成に応じて、いくつかの対処法があります。ここでは最も効果的な戦略を紹介します。

1. 変数やLocalsからロジックを制御する(推奨)countをリソースの出力(output)に依存させるのではなく、そのリソースを定義する入力(input)に依存させます。CIDRブロックのリストに基づいてサブネットを作成している場合は、その同じリストを使用してインスタンスの数を決定します。

誤った方法:

resource "aws_subnet" "example" {
  count      = 3
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.${count.index}.0/24"
}

resource "aws_instance" "server" {
  # エラー: サブネットが作成されるまでIDは不明
  count         = length(aws_subnet.example[*].id)
  ami           = "ami-123456"
  instance_type = "t3.micro"
}

正しい方法:

locals {
  subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
}

resource "aws_subnet" "example" {
  for_each   = toset(local.subnet_cidrs)
  vpc_id     = aws_vpc.main.id
  cidr_block = each.value
}

resource "aws_instance" "server" {
  # 成功: local.subnet_cidrsはPlan時に確定している
  for_each      = toset(local.subnet_cidrs)
  ami           = "ami-123456"
  instance_type = "t3.micro"
  subnet_id     = aws_subnet.example[each.value].id
}

2. フィルター付きのデータソースを使用する既存のリソースや別のステートファイルで管理されているリソースをカウントする場合は、フィルター付きのdataソースを使用します。フィルターが静的な文字列であれば、Terraformは多くの場合Planフェーズでデータソースを解決できます。

data "aws_subnets" "existing" {
  filter {
    name   = "vpc-id"
    values = [var.vpc_id]
  }
}

resource "aws_instance" "worker" {
  count         = length(data.aws_subnets.existing.ids)
  ami           = "ami-xxxxxx"
  instance_type = "t2.micro"
}

3. 「2段階」のApply(暫定的な修正)すぐにコードをリファクタリングできない緊急の場合は、まず依存先のリソースをターゲットにして、Terraformに属性を認識させることができます。これは手動の回避策であり、CI/CDパイプラインにおける長期的な解決策ではありません。

  • terraform apply -target=aws_subnet.example を実行します。
  • サブネットが存在し、そのIDがステートファイルに保存されたら、通常の terraform apply を実行します。 IDがステートに保存されたことで、Terraformは2回目の実行のPlanフェーズでlength()を解決できるようになります。

動作確認修正が機能したことを確認するには、Planを実行し、出力されるリソース数を確認します。

terraform plan

修正が成功していれば、「depends on resource attributes」エラーの代わりに、計画されたリソースの明確なリスト(例:Plan: 5 to add, 0 to change, 0 to destroy)が表示されます。for_eachを使用している場合は、Plan出力のキーが (known after apply) ではなく、期待される静的な識別子(CIDRブロックや名前など)と一致していることを確認してください。

予防策

  • 静的なキー: for_each のキーには、データベースIDや生成されたUIDではなく、常に静的な文字列(名前、CIDR、タグなど)を使用してください。
  • count = length(data.something.ids) を避ける: そのデータソースが同じワークスペース内で作成されたリソースに依存している場合、失敗する可能性が高いです。
  • 入力主導の設計: リソース数の「信頼できる情報源(Source of Truth)」が常に変数やLocalsの定数になるようにモジュールを構成してください。

Related Error Notes