TL;DR: The 30-Second Fix
This error hits because Terraform 0.13 and later require a full namespace (like hashicorp/aws) instead of just a short name (aws). If your code looks correct but the error persists, your state file is still using the old format. Run this command to fix it:
terraform state replace-provider "registry.terraform.io/-/aws" "hashicorp/aws"
Once finished, run terraform init to sync everything.
Why This Error Happens
Before version 0.13, Terraform was a bit of a walled garden. It assumed every provider came directly from HashiCorp. You could just write provider "aws" and it worked. However, as the ecosystem grew to thousands of community providers, Terraform moved to a hierarchical namespace on the official Registry.
The Invalid legacy provider address message is Terraform's way of saying it found a provider named aws but doesn't know who owns it. It uses registry.terraform.io/-/aws as a temporary placeholder. You have to tell Terraform that this "legacy" provider is actually the official hashicorp/aws version.
Three Ways to Fix the Migration
1. Explicitly Define Providers in Your Code
Your .tf files need to tell Terraform exactly where to fetch providers. Open your versions.tf or main.tf and add a required_providers block. This is especially important if you are using specific versions like 3.x or 4.x.
terraform {
required_version = ">= 0.13"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}
2. Remap the Provider in Your State File
Even if you fix your code, your terraform.tfstate file might still be clinging to the old names. For projects with hundreds of resources, you don't want to edit the JSON manually. Instead, use the built-in CLI tool to swap the addresses.
Run these commands based on which providers you use:
# For AWS
terraform state replace-provider "registry.terraform.io/-/aws" "hashicorp/aws"
# For Azure
terraform state replace-provider "registry.terraform.io/-/azurerm" "hashicorp/azurerm"
# For Google Cloud
terraform state replace-provider "registry.terraform.io/-/google" "hashicorp/google"
Terraform will list the changes and ask for a yes to confirm. This updates the internal "address book" for your infrastructure.
3. Use the Automated Upgrade Tool
If you are still on the v0.13 binary, you can let Terraform do the heavy lifting. Run this in your root directory:
terraform 0.13upgrade
This tool scans your configuration and automatically generates the necessary required_providers blocks. It’s a great timesaver for complex environments with multiple modules.
Hunting Down Hidden Legacy References
Sometimes the error sticks around because a third-party module or a terraform_remote_state data source is still using the old naming convention. If the standard fixes fail, you need to see what's happening inside the state file.
Pull your state to a local file to inspect it:
terraform state pull > my_infrastructure.json
State files can be massive—sometimes 5,000+ lines of dense JSON. To make sense of it, I often use a YAML ↔ JSON Converter. Converting that messy JSON into YAML makes it much easier to scan for provider: provider.aws. If you find one, it means a resource is still tied to the legacy address. Pro tip: Use local or browser-only tools like ToolCraft to keep your sensitive state data off third-party servers.
How to Verify the Fix
Don't assume it's fixed just because the command finished. Run these three checks:
- Initialize: Run
terraform init. It should download the provider from the fullhashicorp/awspath. - Inspect: Run
terraform providers. Look for any entries containing a dash (-). You want to see cleanregistry.terraform.io/hashicorp/...paths. - Plan: Run
terraform plan. If the error is gone and you see "No changes. Your infrastructure matches the configuration," you are officially migrated.
Quick Command Reference
Goal
Command
Fix config automatically
`terraform 0.13upgrade`
Update state manually
`terraform state replace-provider [OLD] [NEW]`
Audit all providers
`terraform providers`

