Terraform records, for every resource in state, which provider configuration created it. If that configuration disappears from the code while the resource still exists, Terraform cannot refresh or destroy it and refuses to continue.
There are two quite different situations behind the same heading.
Situation 1: You deleted a provider block
To work with aws_instance.web its original provider configuration at
provider["registry.terraform.io/hashicorp/aws"].eu_west_1 is required,
but it has been removed.
The .eu_west_1 is an alias. Something like this was removed:
provider "aws" {
alias = "eu_west_1"
region = "eu-west-1"
}
The resources it created are still in state and still exist in AWS. Terraform needs credentials and a region to talk to them, which is exactly what the block provided.
Put it back, destroy the resources properly, then remove it:
provider "aws" {
alias = "eu_west_1"
region = "eu-west-1"
}
terraform plan -destroy -target='aws_instance.web'
terraform apply -destroy -target='aws_instance.web'
# now delete the provider block
terraform plan
Deleting real infrastructure and its provider block in one change is the mistake. Remove the resources first, apply, then remove the provider.
If the resources are already gone
Sometimes the infrastructure was deleted outside Terraform and only state remembers it. Then you want the state entries removed without touching anything:
terraform state list | grep aws_instance
terraform state rm 'aws_instance.web'
terraform state rm forgets the resource without destroying it. Take a state backup first, because this is not reversible in place:
terraform state pull > backup.tfstate
If the resources still exist and you state rm them, they become orphans: running, billing, and unmanaged. That is the failure mode to be careful about, and it is why restoring the provider block and destroying properly is the better path whenever the resources are real.
Situation 2: A module is not receiving an aliased provider
Error: Missing required provider configuration
The provider aws.replica is required but no configuration is present.
Modules inherit the default provider configuration automatically. They do not inherit aliased ones. A module that needs an alias must declare it and be given it explicitly.
In the module:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
configuration_aliases = [aws.replica]
}
}
}
resource "aws_s3_bucket" "replica" {
provider = aws.replica
bucket = "acme-replica"
}
In the root:
provider "aws" {
region = "eu-west-1"
}
provider "aws" {
alias = "replica"
region = "us-east-1"
}
module "buckets" {
source = "./modules/buckets"
providers = {
aws = aws # the default
aws.replica = aws.replica # the alias
}
}
The providers map is required once the module declares configuration_aliases. Note that passing providers at all switches off inheritance, so if you map the alias you must map the default too, or the module loses it.
Check what a module is actually getting:
terraform providers
Provider blocks inside modules
A child module that declares its own provider block works and is discouraged, for exactly the reason this error exists: the module's callers cannot then remove or change it, and terraform destroy on a removed module fails because the provider went with it.
The pattern that avoids this is for modules to declare required_providers and receive configurations from the root. Only root modules should contain provider blocks. A count or for_each on a module whose provider is declared internally is rejected outright for the same reason.
After a refactor
Moving resources between modules changes their state addresses but not their provider references. If the target module has no matching provider configuration, this error appears during the move.
Prefer a moved block over terraform state mv, since it is reviewable and travels with the code:
moved {
from = aws_s3_bucket.old
to = module.buckets.aws_s3_bucket.replica
}
Confirm the target module receives the provider the resource was created with before applying.
A checklist
- Read the provider address in the error, including anything after the dot.
- Alias present → a
providerblock with that alias was removed. - Resources still real → restore the block, destroy them, then remove it.
- Resources already gone →
terraform state pull > backupthenterraform state rm. - Never
state rma resource that still exists unless you intend to orphan it. Missing required provider configuration→ a module needs an alias passed explicitly.- Declare
configuration_aliasesin the module and map both default and alias inproviders. - Keep
providerblocks in root modules only.
Frequently Asked Questions
Why does Terraform need the provider configuration to destroy something?
Because destroying a resource means calling the provider's API, and the provider configuration is what supplies the credentials, region and endpoint to call. State records which provider configuration created each resource precisely so Terraform can reach it again later. Remove the block and Terraform still knows the resource exists but has no way to talk to it, so rather than guess at a default that might point at the wrong account or region, it stops and tells you the configuration is missing.
What is the right order for removing a provider and its resources?
Remove the resources first and apply, then remove the provider block in a second change. Deleting both at once leaves state holding objects whose provider is gone, which is exactly this error. If you have already done it, restoring the provider block temporarily is the cleanest recovery: put it back, run a targeted destroy on the affected resources, confirm state is clean, and only then delete the block again.
Do modules inherit provider configurations automatically?
They inherit the default configuration, and not aliased ones. A module that needs an alias must declare it in required_providers with configuration_aliases, and the caller must pass it in the providers map. There is an important side effect: supplying a providers argument at all disables automatic inheritance for that module, so if you map an alias you must also map the default explicitly or the module will lose it.
When is terraform state rm the right answer?
Only when the real infrastructure is already gone and state is the only thing that still remembers it, or when you deliberately intend to stop managing a resource without destroying it. Running it on a resource that still exists orphans that resource: it keeps running, it keeps billing, and nothing manages it any more. Always take a backup with terraform state pull > backup.tfstate first, because the operation cannot be undone in place and recovering means pushing the backup back.
Should modules declare their own provider blocks?
No, as a rule. A provider block inside a child module cannot be overridden or removed by its callers, which makes the module impossible to use in a second region and makes terraform destroy fail once the module is removed, since the provider configuration disappears with it. Terraform also refuses to allow count or for_each on such a module. Declare required_providers in the module, accept configurations from the root, and keep provider blocks in root modules only.