Skip to main content
DevOps Insightsguides & answers

Terraform · troubleshooting

Error: Duplicate resource configuration

Two resource blocks in the same module have the same type and name, so Terraform cannot tell which one you mean. Usually the same block was pasted into two .tf files, or a copied file such as "main copy.tf" is still in the directory. Delete the extra copy, or rename one block; if it is already applied, add a moved block when you rename it, or Terraform destroys and recreates it.

Reproduced on Terraform 1.14.0, . Where the text says “reproduced”, the behaviour was run on that version, not taken from documentation.

First published

New to this? Read what is actually happening first, then come back to the steps.

On this page · 8 sections

Before you start

  • The configuration directory.

Run this first

step 1 of 1
terraform validate

Look for was already declared at FILE:LINE

Lists every duplicate with both file locations, without contacting any provider.

Work out which cause you have

A few questions to narrow the list. Every answer ends in a command that confirms or rules the cause out — this cannot see your cluster, so nothing here is a certainty until you have checked.

Narrow it down

0 answered · nothing is sent anywhere

Is one of the two locations a copy of another file?

Cause space

3 of 3 still possible

  • A copied or backup .tf file is still in the directoryCommon
  • The same block was pasted twice, or two people added itCommon
  • You need to rename a block that is already appliedOccasional

Nothing ruled out yet. Answer the question above and the branches your answer eliminates will strike through here.

Or diagnose it manually

In this order. The first command usually contains the whole answer.

  1. Step 1

    terraform validate

    Lists every duplicate with both file locations, without contacting any provider.

    Look for was already declared at FILE:LINE

Every cause, and how to fix it

Ordered by how often each one turns out to be the answer.

A copied or backup .tf file is still in the directory

Common

A file duplicated in the editor or file manager, such as main copy.tf or main-old.tf, still ends in .tf, so Terraform loads it.

Confirm

ls -la *.tf *.tf.json 2>/dev/null

A copy or backup of another file in the list; the error names both locations

Fix

  • Check which of the two files holds the version you want to keep (the error names both). Then delete the other, or rename it so it no longer ends in .tf (main.tf.bak is ignored).
  • Better, keep old versions in Git rather than in the directory.

The same block was pasted twice, or two people added it

Common

A block copied as a starting point for a second resource and not renamed, or a merge that kept both sides.

Confirm

grep -rn 'resource "TYPE" "NAME"' --include='*.tf' .

Two matches in files directly in this directory. A match in a subdirectory is a separate module, not the duplicate

Fix

  • If both should exist, give the second a different name.
  • If only one should, first check which block matches the object in state: terraform state show TYPE.NAME. Then delete the other.

You need to rename a block that is already applied

Occasional

When the duplicate's name is already in state and you rename one of the two blocks, Terraform plans to destroy the old address and create the new one.

Confirm

terraform plan

will be destroyed alongside will be created for what is really one object

Fix

  • Add a moved block from the old address to the new one, and plan again: it should say has moved to and plan no changes.
moved {
  from = terraform_data.web
  to   = terraform_data.frontend
}

Reproduced on Terraform 1.14.0: 0 to add, 0 to change, 0 to destroy.

Understanding it properly

Skip this if you are mid-incident — the working part of the page is above. Worth reading afterwards, because understanding the mechanism is what stops the next one.

In plain terms

Terraform reads every .tf file in a directory as one configuration, so file boundaries do not separate anything. Two blocks with the same type and name, even in different files, are one name used twice, and Terraform refuses to guess which you meant.

Words used on this page

Resource address
TYPE.NAME, such as aws_instance.web. It must be unique within a module, and it is how state remembers each object.
Override file
A file named override.tf or ending in _override.tf. Its blocks are merged into existing ones instead of being added.
moved block
Tells Terraform an existing object has a new address, so renaming does not destroy and recreate it.
What is actually happening

Reproduced on Terraform 1.14.0 with the same resource block in main.tf and web.tf: Error: Duplicate resource "terraform_data" configuration, A terraform_data resource named "web" was already declared at main.tf:1,1-32. Resource names must be unique per type in each module. terraform init printed each duplicate error twice.

Only files ending in .tf or .tf.json are read. A backup named main.tf.bak was ignored, but a copy named main copy.tf, which is how macOS Finder names a duplicate, caused the error.

A file ending in _override.tf did not cause it: Terraform merged its block into the original, and the plan showed the override's value.

Duplicate data, variable and output blocks fail the same way with their own wording: Duplicate data "TYPE" configuration, Duplicate variable declaration and Duplicate output definition.

How to tell this is your problem
WhereWhat you see
terraform init, validate or planError: Duplicate resource "TYPE" configuration ... A TYPE resource named "NAME" was already declared at FILE:LINE. Resource names must be unique per type in each module.

How to know it is actually fixed

  • terraform validate succeeds, and terraform plan shows no unexpected destroy.

Stopping it happening again

  • Keep old versions in Git, never as extra .tf files in the directory.
  • Run terraform validate in CI on every pull request.

Sources

Behaviour described here is drawn from official documentation. Where a figure could not be confirmed on an official page it is attributed in the text rather than stated as canonical.

Did this get you to an answer?

No text box on purpose — please do not paste production logs anywhere

Something wrong or out of date? Report it