エラーの内容
Error: Provider configuration not present
To work with module.networking.aws_vpc.main its original provider
configuration at module.networking.provider["registry.terraform.io/hashicorp/aws"].eu_west
must be available in the state, but is no longer present.
これはステートの不一致です。Terraformはterraform.tfstate内に、プロバイダーエイリアスを使って作成されたリソースを見つけましたが、そのエイリアスが現在の設定から削除されています。エイリアスがなければ、TerraformはそのリソースをPlan・Apply・Destroyできません。AWSインフラ自体は問題ない可能性が高いですが、Terraformは操作に必要なハンドルを失った状態で動けなくなっています。
なぜこのエラーが発生するのか
terraform.tfstate内のすべてのリソースはプロバイダーのフィンガープリントを持っています。モジュール内でプロバイダーエイリアスを使用すると、そのエイリアスはリソースのIDに紐付けられます。エイリアスをリネームしたり、削除したり、モジュールに渡し忘れたりすると、Terraformはリソースを管理するためのハンドルを失います。
よくある原因:
- モジュール呼び出しから
providersブロックを削除またはコメントアウトした - プロバイダーエイリアスをリネームした(例:
aws.secondary→aws.eu) - ルートモジュールの
providerブロックを削除した - リソースをDestroyする前にモジュールブロックを丸ごと削除した
- チームメンバーがprovidersマップをリファクタリングした際に、モジュール呼び出し側の更新を忘れた
根本原因:モジュールにおけるプロバイダーエイリアスの仕組み
このエラーを引き起こす典型的なマルチリージョン構成は以下の通りです:
# root/main.tf — 2つのAWSプロバイダー設定
provider "aws" {
region = "us-east-1"
}
provider "aws" {
alias = "eu_west" # エイリアス名が重要
region = "eu-west-1"
}
# モジュール呼び出し — エイリアス付きプロバイダーを明示的に渡す
module "networking" {
source = "./modules/networking"
providers = {
aws = aws.eu_west
}
}
子モジュール内では、リソースはこのエイリアス付きプロバイダーを使用します:
# modules/networking/main.tf
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
Terraformはそのリソースをmodule.networking.provider["registry.terraform.io/hashicorp/aws"].eu_westに紐付けてステートに記録します。providersマップを削除するかeu_westをリネームすると、Terraformは元の設定を見つけられなくなり、このエラーが発生します。
修正方法1:モジュール呼び出しにプロバイダーエイリアスを復元する
ほとんどのケースでは、誰かが誤ってprovidersブロックを削除または変更しています。リソースを最初に作成した時と全く同じ状態に戻すことで、エラーはすぐに解消されます。
# ステップ1:ステートが期待するエイリアスを確認する
terraform state show module.networking.aws_vpc.main
出力のproviderフィールドを確認します。Terraformが期待する正確なエイリアスパスが表示されます:
provider = "provider[\"registry.terraform.io/hashicorp/aws\"].eu_west"
# ステップ2:ルートモジュールに一致するエイリアスがあることを確認する
provider "aws" {
alias = "eu_west" # ステートの名前と完全に一致させる
region = "eu-west-1"
}
# ステップ3:モジュール呼び出しで渡す
module "networking" {
source = "./modules/networking"
providers = {
aws = aws.eu_west
}
}
さらに堅牢にするため、子モジュールにconfiguration_aliasesを宣言しましょう。これにより、providersマップが欠落している場合にPlan時にエラーとして検出でき、気づかないまま問題を引き起こすことを防げます:
# modules/networking/versions.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
configuration_aliases = [aws]
}
}
}
# ステップ4:修正を確認する
terraform plan
プロバイダーエラーが出なくなり、Planに想定通りの変更のみが表示されれば完了です。
修正方法2:エイリアスをリネームしたい場合
エイリアスのリネームは単なる名前変更ではありません。Terraformは全く別のプロバイダーとして扱います。ステート内のリソースは古い名前を参照しているため、aws.eu_westをaws.euに置き換えるだけでは解決できません。
オプションA — 古いエイリアスでリソースをDestroyし、新しいエイリアスで再作成する:
# 1. 一時的にエイリアスを古い名前に戻す
provider "aws" {
alias = "eu_west" # 古い名前
region = "eu-west-1"
}
module "networking" {
source = "./modules/networking"
providers = { aws = aws.eu_west }
}
# 2. リソースをクリーンにDestroyする
terraform destroy -target=module.networking
# 3. エイリアスをリネームしてモジュール呼び出しを更新する
provider "aws" {
alias = "eu" # 新しい名前
region = "eu-west-1"
}
module "networking" {
source = "./modules/networking"
providers = { aws = aws.eu }
}
# 4. 再作成する
terraform apply
オプションB — ステートから削除して再インポートする(再作成できない本番リソースの場合):
# 1. TerraformのステートからリソースをRemoveする
# (実際のクラウドリソースは削除されません)
terraform state rm module.networking.aws_vpc.main
# 2. .tfファイル内でエイリアスをリネームする
# 3. 新しいプロバイダーパスで既存リソースをインポートする
terraform import module.networking.aws_vpc.main vpc-0abc123def456789ab
まずterraform state listを実行して、古いエイリアスに紐付いているリソースの全リストを取得してください。その後、各リソースに対してstate rmとimportの手順を繰り返します。
修正方法3:モジュールを完全に削除したい場合
リソースをDestroyする前にモジュールブロックを削除することが、このエラーに陥る典型的なパターンです。TerraformはDestroyオペレーションをPlanするためにプロバイダー設定が必要ですが、モジュールブロックを削除するとその設定も失われます。
# 誤ったアプローチ — 'Provider configuration not present'エラーに直結する:
# 1. モジュールブロックを削除する
# 2. terraform applyを実行する ← ここでエラー
# 正しいアプローチ:
# 1. モジュールブロックはそのままにしておく
terraform destroy -target=module.networking
# 2. Destroyが成功した後にのみ、.tfファイルからモジュールブロックを削除する
# 3. applyを実行する(変更なしのはず)
terraform apply
確認手順
完了と判断する前に、以下の3つのチェックを実行してください:
# 1. プロバイダーエラーなしにPlanが実行できること
terraform plan
# 2. リソースがまだステートに存在することを確認する
terraform state list | grep module.networking
# 3. ステート内のプロバイダーパスがエイリアスと一致することを確認する
terraform state show module.networking.aws_vpc.main | grep provider
最後のコマンドの出力は次のようになるはずです:
provider = "provider[\"registry.terraform.io/hashicorp/aws\"].eu_west"
このエイリアス名は、ルートのproviderブロックに記載されているものと一致している必要があります。一致していない場合はまだ完了していません。
再発防止策
- 削除前にDestroyする:モジュールブロックの削除やエイリアスの廃止を行う前に、必ず
terraform destroy -target=module.xxxを実行してください。設定の削除とApplyを同時に行うと問題が発生します。 - 子モジュールで
configuration_aliasesを宣言する:呼び出し元がprovidersマップを明示的に渡すことを強制します。マップが欠落している場合は実行時エラーではなくPlan時エラーとして検出されます。 - エイリアスのリネームは破壊的変更として扱う:そのエイリアスを使用しているすべてのモジュール呼び出しを同じコミットで更新してください。本番環境に適用する前に、非本番ワークスペースでリネームをテストしてください。
- 大規模なリファクタリング前にステートを確認する:モジュールを再構成する前に
terraform state listを実行してください。どのリソースがどのエイリアスに紐付いているかが正確に把握でき、リソースが孤立するのを防げます。 - リージョンごとに別々のステートファイルを使用する:複雑なマルチリージョン構成の場合、リージョンごとに1つのTerraformルートモジュールを使用することでエイリアス管理がほぼ不要になります。ファイル数は増えますが、エイリアスに起因する問題が大幅に減少します。
Terraformと並行してterragrunt.hclや変数入力ファイルなどのYAMLベースの設定を扱っている場合は、ToolCraftのYAML ↔ JSONコンバーターを使うと、terraform initが実行される前にインデントやフォーマットの問題を検出できます。

