エラーメッセージ
terraform plan または terraform validate を実行すると、次のようなエラーが表示されます:
Error: Unsupported argument
on main.tf line 42, in resource "aws_instance" "web":
42: instance_type_size = "t3.micro"
An argument named "instance_type_size" is not expected here.
Terraformは特定の行を指して、その属性を認識できないと伝えています。これは実は有用な情報です — エラーがどこを見ればよいかを正確に教えてくれています。原因はほぼ必ずこの3つのいずれかです:タイポ、大文字小文字の不一致、またはコードとプロバイダープラグイン間のバージョンのずれ。
なぜこのエラーが起きるのか
すべてのTerraformプロバイダーはスキーマを持っています — 各リソースタイプに対して有効な引数の厳密なリストです。リスト外のものを指定するとパーサーが即座に停止します。最も一般的な原因は以下の通りです:
- タイポ: 正しい引数が
amiなのにami_idと書いてしまう。余分な単語1つで即エラーになります。 - 大文字小文字の誤り: Terraformは全て
snake_caseを使用します。CloudFormationやARMテンプレートから移行すると、instance_typeの代わりにInstanceTypeと書いてしまいがちです。 - プロバイダーバージョンのずれ: AWSプロバイダーv5.0では
aws_vpcにipv6_ipam_pool_idが追加されました。プロジェクトがv4.xに固定されている場合、その引数はそのバージョンのスキーマには存在しません。 - 非推奨の属性: 引数はメジャーアップデートで削除されることがあります。例えば、S3プロバイダーの
lifecycle_ruleブロックはv3とv4の間で再構成されました。
ステップごとの修正方法
1. タイポと大文字小文字を確認する
まずシンプルなところから始めましょう。属性名を1文字ずつ確認してください。Terraformの組み込みリソース引数は例外なく全て snake_case です。
# WRONG — CloudFormationの習慣でCamelCaseになってしまっている
resource "aws_instance" "example" {
Ami = "ami-12345678"
}
# RIGHT
resource "aws_instance" "example" {
ami = "ami-12345678"
}
また、微妙な単数・複数の違いにも注意してください:security_group_id と security_group_ids。Terraformはこれらを全く別の引数として扱います。
2. 実際に使用しているプロバイダーバージョンを確認する
コードが完全に正しくても、ローカルにインストールされているバージョンに対応していない可能性があります。以下を実行してください:
terraform version
次のような出力が表示されます:
Terraform v1.7.4
on linux_amd64
+ provider registry.terraform.io/hashicorp/aws v4.67.0
次に、versions.tf または main.tf のバージョン制約を確認します:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0" # 4.xに固定 — 5.xの機能は使用不可
}
}
}
使用している属性がv5.0で導入されたもので、v4.xに固定されている場合、それが原因です。
3. 最新版ではなく使用中のバージョンのドキュメントを読む
Terraform Registryはデフォルトで最新のプロバイダードキュメントを表示します。その情報をそのまま信じてはいけません。バージョンのドロップダウンを使って .terraform.lock.hcl ファイルの内容と一致させ、そのバージョンでリソースを検索して引数が存在することを確認してください。
ロックファイルには実際にインストールされているものが正確に記載されています:
provider "registry.terraform.io/hashicorp/aws" {
version = "4.67.0"
constraints = "~> 4.0"
}
4. 必要に応じてプロバイダーを更新する
v5.xの機能が必要な場合は、バージョン制約を更新してから以下を実行します:
terraform init -upgrade
これにより、更新した制約の範囲内で最新バージョンが取得され、ロックファイルが再生成されます。まず本番以外のワークスペースでテストしてください — メジャーバージョンアップには他のリソースにも影響する破壊的変更が含まれることが多いです。
5. ブロックと属性の違いに注意する
属性のように見えるものが、実際はネストされたブロックである場合があります。エラーメッセージの文言がヒントになります:
- 属性をブロックとして書いた場合:
=記号が抜けています — 例:tags {}ではなくtags = {}と書く必要があります。 - ブロックを属性として書いた場合: 不要な
=が追加されています — 例:ingress {}とすべきところをingress = {}と書いてしまっています。
確認方法
変更を加えた後、以下の3つのコマンドを順番に実行してください:
- フォーマット:
terraform fmt— 空白を正規化し、明らかな構文の問題を検出します。 - 検証:
terraform validate— ローカルのみのチェックで、APIコールは不要です。Success! The configuration is valid.と表示されればスキーマエラーは解消されています。 - プラン:
terraform plan— プロバイダーが実際のクラウドの状態に対して設定を処理し、validateでは検出できないランタイムの問題を確認します。
予防のヒント
- HashiCorp VS Code拡張機能: エディターにスキーマ対応のIntelliSenseを追加します。
.terraformフォルダー内のプロバイダーに基づき、サポートされていない引数はplanを実行する前にリアルタイムで下線が引かれます。 - バージョンを固定する:
~> 5.0を指定したrequired_providersブロックにより、プロバイダーがv6.0をリリースして引数が変更・削除された際の予期せぬ破損を防ぎます。 - アップグレード前にChangelogを読む: プロバイダーのGitHubリポジトリには
CHANGELOG.mdが管理されています。「Breaking Changes」セクションは通常短いです — 5分確認するだけで何時間ものデバッグを節約できます。

