There is a category of bug that does not crash, does not warn, and passes review. The tool reads your configuration, understands it differently than you do, and proceeds confidently. You find out weeks later, when something is running somewhere it should not be.
Terragrunt shipped one of those for years. Two dependency blocks with the same label parsed without complaint, and every reference to that label quietly resolved to whichever block happened to come last. Version 1.1.4, released on 27 August 2026, finally makes it say something.▸The 60-second version — flip through the deck8 slides · swipe →
The configuration
Here is the whole bug. It fits on a screen, which is part of why it survived so long.
dependency "vpc" {
config_path = "../vpc-us-east-1"
}
dependency "vpc" {
config_path = "../vpc-us-west-2"
}
inputs = {
# Reads ../vpc-us-west-2. Always did.
vpc_id = dependency.vpc.outputs.vpc_id
}
Read that as a reviewer. Two regions are declared. The intent is obvious and the syntax is valid. Nothing about it suggests that one of those blocks is decorative.
What actually happened is that HCL let the second block shadow the first, Terragrunt kept the last one it parsed, and dependency.vpc meant us-west-2 from then on. The us-east-1 block still ran its dependency, still got planned, still showed up in the graph. Its outputs just never reached anything.
Why this shape is the dangerous one
I have written before about the other end of this category. On a client migration, terraform plan wanted to replace a production database. Nobody had typed destroy. The module had been swapped, the resource address had changed, and Terraform tracks resources by address rather than by what they are, so a changed address reads as delete-then-create. The plan was correct. It was also one apply away from taking the database with it.
Same shape as this one. The tool did exactly what it was told. What it was told was not what anyone meant.
Loud failures are a solved problem. Every pipeline in the world catches those. The ones that cost real money are the configurations that are wrong and legible at the same time.
The fix
Terragrunt 1.1.4 warns when it finds duplicate labels. If you want it to stop, there is a strict control:
terragrunt run plan --strict-control duplicate-dependency-labels
/path/to/terragrunt.hcl: dependency vpc is declared more than once; every dependency needs an address of its own
The error names the address the blocks are fighting over, which is the useful half. Fixing it is mechanical: give every block a label of its own. If a configuration was relying on the shadowing, deliberately or otherwise, keep only the block that was winning and delete the rest, because that is what was running.
Put the flag in CI before you need it
Strict controls in Terragrunt are a staged deprecation mechanism. A behaviour becomes a warning, then an error under strict mode, then eventually the only behaviour. The documentation's own recommendation is to enable strict controls in non-production pipelines so incompatibilities surface early, while you still get to choose when to deal with them.
- Add
--strict-control duplicate-dependency-labelsto the non-prod plan job first, not to prod. - Run it once across every unit. If nothing fires, the flag costs you nothing and stays as a guard.
- If it fires, treat each hit as an audit question rather than a rename: which block was actually running, and is that the one you wanted?
- Only then promote the flag to the production pipeline.
The point of the middle step is that renaming the label changes behaviour. A duplicate that has been shadowing since 2024 means half your configuration has been dead code, and the moment you give both blocks real labels, the previously-ignored one wakes up and starts feeding real values into real resources. That is a change, and it deserves a plan you read carefully.
A crash tells you where it broke. A silent misread lets you ship it.
Also in 1.1.4
One smaller change in the same release, worth knowing if you scaffold from the command line. terragrunt scaffold used to write # TODO placeholders for every input and leave you to fill them in, while scaffolding the same component from the Catalog TUI opened a form and collected the values properly. Now the command opens that same form.
| Context | Behaviour |
|---|---|
| Interactive terminal | Opens the form, lists the source's variables or values.* references |
--non-interactive | Placeholders, exactly as before |
stdin is not a terminal | Placeholders, exactly as before |
| Source asks for nothing | Skipped |
The CI-safety design is the part I appreciate. A scaffold running inside a pipeline, or driven by another program, behaves exactly as it did. Nobody's automation breaks because an interactive nicety was added.
Go grep your Terragrunt repos for duplicate dependency labels before the flag does it for you. If you find one, I would like to hear how long it had been there. Find me on LinkedIn.