エラーメッセージスムーズなデプロイを期待して terraform plan を実行したものの、HCLで問題が発生することがあります。実行計画(plan)が表示される代わりに、次のようなエラーで停止します:
Error: Reference to undeclared resource
on main.tf line 42, in resource "aws_eip" "static_ip":
42: instance = aws_instance.web_server.id
A managed resource "aws_instance" "web_server" has not been declared in the root module.
原因は何ですか?Terraformがただ意地悪をしているわけではありません。その静的解析エンジンは厳格なコンパイラのように動作します。初期化フェーズ中に、すべての参照を特定の resource、data ソース、または variable ブロックにマッピングできない場合、処理の続行を拒否します。実際のクラウド環境に変更を加える前に、インフラストラクチャの1対1のマップが必要なのです。
このエラーは通常、次の3つの理由で発生します:
- 恐ろしいタイポ(打ち間違い): リソース名を
web_appと定義したのに、42行目ではweb_serverと入力してしまった。- モジュールの隔離: 子モジュール内でリソースを定義したが、ルートのmain.tfから直接呼び出そうとしている。- ゴースト参照: リソースブロックを削除またはコメントアウトしたが、それを参照している出力(output)やローカル変数が残っている。## 修正方法### 1. タイポを特定するTerraformの識別子は、大文字と小文字を区別し、記号(アンダースコアかハイフンかなど)にも厳格です。パーサーにとってweb-serverとweb_serverは完全に異なるオブジェクトです。リソース定義ブロックと、エラーが発生した行の内容を直接比較してください。 間違いの例:
resource "aws_instance" "api_v1" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
}
output "server_id" {
value = aws_instance.api.id # エラー: "api" は "api_v1" と一致しません
}
修正: 名前を完全に一致させます。
output "server_id" {
value = aws_instance.api_v1.id
}
2. モジュール間のギャップを埋めるTerraformのモジュールはブラックボックスです。./modules/vpc 内でリソースを定義した場合、そのリソースはそのモジュール内でのみプライベートな存在です。ルートから module.vpc.aws_vpc.main.id のように直接内部を参照することはできません。
修正方法:明示的な Output を使用する
まず、子モジュール内(例:./modules/vpc/outputs.tf)で値をエクスポートします:
output "vpc_id" {
value = aws_vpc.main.id
}
次に、ルート設定において、リソースそのものではなくモジュールの出力を参照します:
resource "aws_subnet" "public" {
vpc_id = module.network.vpc_id # これで正しく動作します
}
3. 「ゴースト」ロジックのクリーンアップリファクタリング中に、AWSのコストを節約するためにリソースブロックをコメントアウトしたが、local 値や tags マップがまだそのリソースに依存していることを忘れてしまうことがよくあります。Terraformは、コード内で現在アクティブではないものへの参照を見つけると、エラーを吐きます。
修正: エラーに記載された特定のリソース名を、プロジェクト全体で検索(VS Codeなら Ctrl+Shift+F)します。outputs.tf や locals.tf に残っている古い参照を削除またはコメントアウトしてください。
検証ステップすぐに apply を再実行しないでください。次の2つのツールを使用してロジックを検証しましょう:
- Validate:
terraform validateを実行します。これはHCLの構文と内部的な整合性をローカルでチェックします。クラウドに接続することなく、数秒で未宣言のリソースを検出できます。- Plan:terraform planを実行します。バリデーションに合格すれば、planによって参照が実際の値に解決されることが確認できます。## 再発防止のプロのコツ- 適切なIDEツールを導入する: VS Code用の公式 HashiCorp Terraform 拡張機能を使用してください。リアルタイムでリンティングを行い、入力中に未宣言のリソースを赤色の下線で示してくれます。- 命名規則を標準化する: 「アンダースコア vs ハイフン」論争のどちらか一方を選び、それを貫いてください。すべてのリソース名にsnake_caseを使用するだけで、これらのエラーの50%を防げます。- モジュールを簡潔に保つ: モジュール間で20個もの出力を受け渡している場合は、関連するリソースをより近くに配置するようにモジュールの境界線を再検討する必要があるかもしれません。

