TL;DR
作業ディレクトリで terraform plan や terraform apply を実行する前に、まず terraform init を実行してください。それだけです。
terraform init
terraform plan
CI/CDで既に init を実行済みなのにまだ発生している場合は、以下の根本原因のセクションをご確認ください。
エラー内容
Error: Module not installed
This module is not yet installed. Run "terraform init" to install all modules required by this configuration.
Terraformは .tf ファイル内に module ブロックを見つけたものの、.terraform/modules/ 配下にダウンロード済みのソースが見当たらない場合にこのエラーをスローします。モジュールのメタデータがまだ存在しないため、Terraformは他の処理を行う前に停止します。
根本原因
たとえば、次のようなモジュールブロックがあるとします:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.1.2"
name = "my-vpc"
cidr = "10.0.0.0/16"
}
Terraformがそのブロックを評価する前に、ディスク上に実際のモジュールソースが必要です。terraform init コマンドがその取得を担います。このコマンドは2か所に書き込みを行います:
.terraform/modules/— ダウンロードされたモジュールファイル.terraform/modules/modules.json— レジストリのメタデータ
.terraform/modules/ ディレクトリが存在しない場合、Terraformは即座に処理を中断します。これは plan が init より先に実行された場合や、誰かが再初期化せずに .terraform/ を削除した場合に発生します。
最もよくあるトリガー:
- リポジトリを新たにクローンした場合 —
.terraform/は(正しく)gitignoreされているため、コミットされることはありません - CI/CDパイプラインで
initステップがスキップされたか、サイレントに失敗した場合 - 新しい
moduleブロックを追加したが、initを再実行しなかった場合 - クリーンアップのために
rm -rf .terraform/を実行し、再初期化を忘れた場合 - 異なるモジュールソースやバージョンが宣言されているブランチへ切り替えた場合
修正方法
方法1 — 標準的な修正(ローカル開発環境)
# Terraformの作業ディレクトリに移動
cd path/to/your/terraform
# 初期化 — モジュールとプロバイダーをダウンロード
terraform init
# これでplanが実行できます
terraform plan
方法2 — 既存の設定に新しいモジュールを追加した場合
既に初期化済みのワークスペースに新しい module ブロックを追加しましたか?新しいソースを取得するために init を再実行してください:
terraform init -upgrade
-upgrade フラグは厳密には必須ではありません(通常の init でも問題ありません)が、良い習慣です — 宣言された制約の範囲内でプロバイダーも最新バージョンに更新されます。
方法3 — CI/CDパイプラインの場合
GitHub Actions、GitLab CIなどでは、init と plan を明示的に別々のステップとして設定してください:
# GitHub Actionsの例
- name: Terraform Init
run: terraform init
working-directory: ./infra
- name: Terraform Plan
run: terraform plan
working-directory: ./infra
リモートバックエンド(S3、GCS、Terraform Cloud)を使用していますか?バックエンドの設定を明示的に渡してください — そうしないと、認証情報が不足している場合に init がサイレントに失敗し、パイプラインがそのまま続行されてしまいます:
terraform init \
-backend-config="bucket=my-tf-state" \
-backend-config="key=prod/terraform.tfstate" \
-backend-config="region=us-east-1"
方法4 — ローカルパスのモジュールが見つからない場合
ローカルパスのモジュールはレジストリのものとは動作が異なります。宣言内容を確認してください:
module "networking" {
source = "../modules/networking"
}
このパスは呼び出し元モジュールからの相対パスとして存在している必要があります。ここでのタイポは init の失敗を引き起こし、init が失敗すると plan も同じエラーをスローします。再実行前に確認してください:
# パスが存在することを確認
ls ../modules/networking
# その後、再初期化
terraform init
方法5 — 作業ディレクトリの不一致
これはモノレポでよく引っかかる問題です。init と plan を異なるディレクトリから実行することが原因です — 各ディレクトリにはそれぞれ独自の .terraform/ が必要です:
# 誤り — initは/infraで実行したが、planは/から実行
cd /infra && terraform init
cd / && terraform plan # ← 失敗、ここには.terraformがありません
# 正しい — 両方のコマンドを同じディレクトリで実行
cd /infra
terraform init
terraform plan
確認方法
init が完了したら、モジュールが正しく配置されていることを確認してください:
# modulesディレクトリが存在し、内容があることを確認
ls .terraform/modules/
# modules.jsonと各モジュールのディレクトリが表示されるはずです
# 出力例:
# modules.json vpc/
terraform plan を実行してください。モジュールの読み込みステージを問題なく通過し、リソースの差分か、おなじみの「No changes」メッセージが表示されるはずです:
terraform plan
# 成功時の出力は以下から始まります:
# Terraform used the selected providers to generate the following execution plan...
予防のヒント
.terraform/を.gitignoreに追加しておきましょう — Terraformの公式テンプレートに含まれていますが、古いリポジトリでは欠落していることがあります。簡単に確認する価値があります。- リポジトリのREADMEに一文追加しましょう:「クローン後に
terraform initを実行してください。」これにより、新しい貢献者がこの問題に遭遇するのを防げます。 - CI/CDでは、
initとplanを別々の名前付きステップとして扱ってください。問題が発生した際に、どのステップで失敗したかがすぐにわかります。 - 深くネストされたモジュールと複雑な
.terraform.lock.hclを扱っていますか?ロックファイルの内容をToolCraftのYAML ↔ JSONコンバーターに貼り付けると、構造的な問題をすばやく特定できます — HCLのキーと値の構文はコンバーターで扱えるほど近いため、目視では見落としやすい括弧の不一致や不正なブロックをフラグアップしてくれます。
クイックリファレンス
# 常にinitを最初に実行
terraform init
# モジュールを追加または変更した後にinitを再実行
terraform init
# プロバイダーとモジュールを許可された最新バージョンにアップグレード
terraform init -upgrade
# モジュールがインストールされていることを確認
ls .terraform/modules/
cat .terraform/modules/modules.json

