シナリオ
既存のAWSリソースをTerraformの管理下に置くためにterraform importを実行すると、コマンドが即座に失敗します:
Error: Cannot import non-existent remote object
While attempting to import an existing object to aws_instance.example,
the provider detected that no object exists with the given id.
Only pre-existing objects can be imported.
リソースはAWSコンソール上で視覚的に存在しているように見えます — あるいは少なくとも、存在していると思っているはずです。このエラーは、TerraformのプロバイダーがあなたのIDで検索を行った結果、何も見つからなかったことを意味します。
原因
importコマンド自体はシンプルです:Terraformはあなたが指定したIDでクラウドAPIを呼び出します。APIが何も返さなければ、このエラーが発生します。原因はほぼ必ず以下のいずれかです:
- リソースIDの誤り — 最も多い原因です。リソースタイプごとにIDのフォーマットが異なるため、混同しやすいです。
- AWSリージョンの誤り — プロバイダーが
us-east-1に設定されているが、リソースがap-southeast-1に存在している場合。 - AWSアカウントの誤り — シェルのクレデンシャルが、リソースを作成したアカウントとは別のアカウントを指している場合。
- リソースがすでに削除済み — importブロックを書き始めた時点では存在していたが、実行前にクリーンアップされた場合。
- リソースタイプの誤り — RDSクラスターのIDを
aws_rds_clusterではなくaws_db_instanceにimportしようとしている場合。
クイックフィックス — 再実行前に診断する
ステップ1:リソースが実際に存在するか確認する
Terraformを操作する前に、AWS CLIで確認します:
# EC2インスタンスの場合
aws ec2 describe-instances --instance-ids i-0abc123def456 --region us-east-1
# S3バケットの場合
aws s3api head-bucket --bucket my-bucket-name
# RDSインスタンスの場合
aws rds describe-db-instances --db-instance-identifier mydb --region us-east-1
CLIも何も返さない場合、または明示的なnot foundエラーが返る場合、リソースは削除されています。削除済みリソースの対処法については、以下のセクションを参照してください。
ステップ2:クレデンシャルが使用するアカウントとリージョンを確認する
aws sts get-caller-identity
aws configure get region
アカウントIDとリージョンを、リソースが実際に存在する場所と比較します。一致しない場合は、プロファイルを切り替えるか、リージョンを明示的に設定します:
export AWS_PROFILE=production
export AWS_DEFAULT_REGION=ap-southeast-1
terraform import aws_instance.example i-0abc123def456
ステップ3:リソースタイプのIDフォーマットを確認する
リソースタイプごとに特定のIDフォーマットが必要です。よく間違えやすいものをいくつか示します:
# EC2インスタンス — インスタンスIDをそのまま使用
terraform import aws_instance.web i-0abc123def456
# セキュリティグループ — sg- IDを使用
terraform import aws_security_group.main sg-0abc123def456
# IAMロール — ARNではなくロール名を使用
terraform import aws_iam_role.deployer my-deployer-role
# S3バケット — バケット名を使用
terraform import aws_s3_bucket.assets my-assets-bucket
# RDSクラスター(aws_db_instanceではなく!)
terraform import aws_rds_cluster.main my-cluster-id
# サブネット — サブネットIDを使用
terraform import aws_subnet.private subnet-0abc123def456
各リソースのTerraformレジストリドキュメントには、ページ下部のImportセクションに常にimport IDフォーマットが記載されています。実行前に確認してください。
ステップ4:詳細出力を有効にして再実行する
まだ原因がわからない場合は、ログを有効にして実行すると、プロバイダーが実際にどのAPIコールを行っているか確認できます:
TF_LOG=DEBUG terraform import aws_instance.example i-0abc123def456 2>&1 | grep -i "describe\|import\|error"
デバッグ出力には正確なAPIコールとレスポンスが表示されるため、不一致の原因が明確になります。
削除済みリソースへの対処
リソースが本当に存在しない場合、2つの対処法があります:
オプションA — importブロックを削除する(Terraform 1.5以降のimportブロック)
新しいHCLベースのimport構文を使用している場合は、ブロックと関連するリソース設定を削除します:
# .tfファイルからこれを削除する:
import {
to = aws_instance.example
id = "i-0abc123def456"
}
resource "aws_instance" "example" {
# ...
}
オプションB — 部分的にimportされた場合はstateエントリを削除する
stateが中途半端にimportされた状態になることがあります。クリーンアップします:
# stateに含まれているか確認
terraform state list | grep example
# 紛れ込んでいた場合は削除
terraform state rm aws_instance.example
オプションC — Terraformに新規作成させる
importブロックを削除してリソースブロックを残した場合、terraform planは新しいリソースとして作成するよう表示します。元のリソースが削除されている場合、これが通常の正しい結果です。
恒久的な対策 — import前に確認する
import操作を行う前の最もクリーンなワークフロー:
#!/bin/bash
# verify-before-import.sh
RESOURCE_ID="$1"
REGION="${2:-us-east-1}"
echo "リージョン $REGION でインスタンス $RESOURCE_ID を確認中..."
aws ec2 describe-instances \
--instance-ids "$RESOURCE_ID" \
--region "$REGION" \
--query 'Reservations[0].Instances[0].State.Name' \
--output text
if [ $? -ne 0 ]; then
echo "リソースが見つかりません — terraform importを実行しないでください"
exit 1
fi
echo "リソースが存在します。importしても安全です。"
importのたびにこれを実行すれば、削除済みまたは存在しないリソースによるこのエラーは二度と発生しません。
確認 — 修正が反映されたかチェックする
IDまたはリージョンを修正してimportを再実行した後:
# 1. importがエラーなく完了するはず
terraform import aws_instance.example i-0abc123def456
# 期待される結果: Import successful!
# 2. stateが正しく設定されているか確認
terraform state show aws_instance.example
# リソースの全属性が表示されるはず
# 3. planを実行 — 理想的には変更なし
terraform plan
# 期待される結果: No changes. Your infrastructure matches the configuration.
importの後もterraform planが変更を表示する場合、.tfファイル内のリソース設定が実際のリソースと一致していないことを意味します。それはドリフトの問題ですが、importエラー自体は解消されています。

