OpenTofu Error: 'Duplicate variable declaration' Two variable Blocks Same Name
Fix OpenTofu's 'Duplicate variable declaration' error: find and remove the second variable block with the same name, often left behind after merges or refactors.
- #opentofu
- #terraform
- #iac
- #troubleshooting
- #errors
Stuck on this OpenTofu error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Exact Error Message
╷
│ Error: Duplicate variable declaration
│
│ on variables.tf line 21:
│ 21: variable "region" {
│
│ A variable named "region" was already declared at variables.tf:3,1-19.
│ Variable names must be unique within a module.
╵
The message names the duplicated variable and points at both the second declaration and the location of the first one it conflicts with.
What It Means
Within a single module, every variable block must have a unique name. OpenTofu loads all .tf files in a module directory and treats them as one combined configuration, so two variable "region" {} blocks — even in different files — collide. When it finds a second declaration of the same name, it stops with Duplicate variable declaration and shows you both locations.
This is a configuration authoring error, not a state or provider problem. It commonly appears after a merge conflict is resolved sloppily, after copy-pasting a block, or after splitting variables across files without noticing an overlap. The same rule applies to output, resource, module, and locals names.
Common Causes
- The same
variableblock was copy-pasted into two files (for examplevariables.tfandmain.tf). - A merge or rebase kept both sides of a conflict, leaving two identical declarations.
- Variables were split into multiple files and one name was duplicated by accident.
- A generated file (from a template or scaffolding tool) redeclares a variable that already exists.
- A leftover
variables.tf.bakor similar file with a.tfextension is being loaded alongside the real one.
Diagnostic Commands
Let OpenTofu report both conflicting locations:
tofu validate
Find every declaration of the duplicated name across the module:
grep -rn 'variable "region"' .
List all .tf files OpenTofu will load, in case a backup file sneaked in:
ls -1 *.tf
Count declarations per variable name to spot any other duplicates:
grep -rhoE 'variable "[a-zA-Z0-9_]+"' *.tf | sort | uniq -c | sort -rn
Step-by-Step Resolution
-
Run
tofu validate. The error lists both the second declaration and thealready declared atlocation of the first. -
Search the whole module directory for the name so you see every copy:
grep -rn 'variable "region"' .
- Decide which declaration is canonical. Keep the one with the correct
type,description, anddefault, and delete the redundant block entirely:
# variables.tf — keep this one
variable "region" {
type = string
description = "AWS region to deploy into."
default = "us-east-1"
}
-
Remove the duplicate from the other file. Do not comment it out — a commented block is fine, but leaving a second live
variable "region"block anywhere will re-trigger the error. -
If the duplicate came from a merge conflict, make sure no conflict markers (
<<<<<<<,=======,>>>>>>>) remain and that only one version survived. -
Check for stray files with a
.tfextension that OpenTofu is loading unintentionally:
ls -1 *.tf
# rename or remove variables.tf.bak, old-variables.tf, etc.
- Validate again to confirm the module now parses cleanly:
tofu validate
Prevention
- Declare each variable exactly once and keep all declarations in a single
variables.tfper module so duplicates are obvious. - Never store backup copies with a
.tfextension in the module directory; OpenTofu loads every.tffile. Use.tf.bakoutside the directory or a separate folder. - Resolve merge conflicts carefully and run
tofu validateimmediately afterward. - Add
tofu validateto CI so duplicate declarations fail before they reach anyone else’s checkout. - Periodically audit declarations with
grep ... | uniq -cto catch overlaps early. The prompt library has prompts that consolidate scattered variable blocks into one clean file.
Related Errors
Duplicate output definition— the same uniqueness rule applied to twooutputblocks.Duplicate resource "type" "name" configuration— two resource blocks sharing type and name.Duplicate required providers configuration— more than onerequired_providersblock in a module.Reference to undeclared input variable— the opposite problem: a reference with no declaration at all.
Frequently Asked Questions
Why does a duplicate in a different file still fail? OpenTofu merges all .tf files in a module directory into one configuration before evaluating it, so names must be unique across the whole directory, not just per file.
Can two modules both declare a variable named “region”? Yes. The uniqueness rule is per module. Two separate modules (different directories) may each declare their own region variable without conflict.
Is a leftover backup file really loaded? Any file ending in .tf (or .tf.json) in the module directory is loaded. A file like variables_old.tf will be parsed and can cause a duplicate. Move or rename it.
Does commenting out the second block fix it? Yes, but deleting it is cleaner. A fully commented-out block is not parsed as a declaration, so only the remaining live block counts.
Where can I find more OpenTofu fixes? Browse the OpenTofu guides for the complete set of error walkthroughs.
Fixed it? Get 500 OpenTofu & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.