-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Describe the bug
When using Terragrunt stacks with template modules (i.e. gets generated into .terragrunt-stack/) that require stack context (e.g. usage of values.x in dependency block), --queue-exclude-dir does not prevent parsing of the excluded directories during dependency discovery. This causes parsing errors because template modules reference stack variables (like values) that are only available in the generated stack context.
Reproduction Steps
Expected Behavior:
--queue-exclude-dir '**/module/*' should completely exclude the module/ directory from both:
- ✅ Execution queue (currently works)
- ❌ Discovery/parsing phase (currently broken)
Actual Behavior:
The excluded directories are still parsed during dependency discovery, causing errors when template modules use stack-specific variables.
Reproduction Steps
Directory Structure:
infra/project-a/
├── terragrunt.stack.hcl # Stack definition
├── staging.tfvars # Stack values
└── module/
└── terragrunt.hcl # Template module (requires stack context)
Template module uses stack variables:
# module/terragrunt.hcl
dependency "project_b" {
config_path = "${get_repo_root()}/project-b/.terragrunt-stack/${values.environment}"
}
Command
cd infra/project-a
terragrunt stack run plan --queue-exclude-dir '**/module/*'
Result:
22:48:05.344 DEBUG Generating: staging (./module) to ./.terragrunt-stack/staging
22:48:05.348 DEBUG Writing values file in ./.terragrunt-stack/staging
# Stack generation succeeds ✓
...
22:48:05.415 ERROR Error: Unknown variable
22:48:05.416 ERROR on ./module/terragrunt.hcl line 5, in dependency "project-b":
22:48:05.416 ERROR 5: config_path = ".../${values.environment}"
22:48:05.416 ERROR There is no variable named "values".
Evidence from Trace Logs:
The stack trace shows this occurs during discovery phase in internal/discovery/discovery.go:
github.com/gruntwork-io/terragrunt/internal/discovery/discovery.go:515
github.com/gruntwork-io/terragrunt/internal/discovery/discovery.go:878
github.com/gruntwork-io/terragrunt/internal/discovery/discovery.go:834
github.com/gruntwork-io/terragrunt/config/config_partial.go:444
github.com/gruntwork-io/terragrunt/config/config_partial.go:318
github.com/gruntwork-io/terragrunt/config/config_partial.go:296
github.com/gruntwork-io/terragrunt/internal/discovery/discovery.go:515github.com/gruntwork-io/terragrunt/internal/discovery/discovery.go:878github.com/gruntwork-io/terragrunt/internal/discovery/discovery.go:834github.com/gruntwork-io/terragrunt/config/config_partial.go:444github.com/gruntwork-io/terragrunt/config/config_partial.go:318github.com/gruntwork-io/terragrunt/config/config_partial.go:296
The discovery phase attempts to parse ./module/terragrunt.hcl as a standalone unit, despite it being excluded via --queue-exclude-dir.
Comparison: Why --queue-include-dir & --queue-strict-include Works
Using --queue-strict-include --queue-include-dir '**/.terragrunt-stack/**/*' works correctly because it prevents discovery from scanning module/ entirely:
22:49:10.487 DEBUG Generating: staging (./module/regional) to ./.terragrunt-stack/staging
22:49:10.505 DEBUG [Partial] Included config ../../../root.hcl has strategy shallow merge
# No attempt to parse ./module/terragrunt.hcl ✓
22:49:10.487 DEBUG Generating: staging (./module) to ./.terragrunt-stack/staging
22:49:10.505 DEBUG [Partial] Included config ../../../root.hcl has strategy shallow merge
# No attempt to parse ./module/regional/terragrunt.hcl ✓
Versions
Terragrunt Version: 0.91.5
Tofu Version: 1.10.6
OS: macOS (darwin 24.5.0)
Additional Notes
builder.go has the following:
// NOTE: We do NOT pass ExcludeDirs to discovery because excluded units need to be
// discovered and reported (for --report-file functionality). The unit resolver will
// handle exclusions after discovery, ensuring excluded units appear in reports.
//
// For now... We can probably use the following once runnerpool has been updated to not expect external
// dependencies in the discovery results.
//
// if !terragruntOptions.IgnoreExternalDependencies {
// d = d.WithDiscoverExternalDependencies()
// }
// Pass include behavior flags
if terragruntOptions.StrictInclude {
d = d.WithStrictInclude()
}
It seems this is intentional but has this side effect. I would imaging we could find a way to still achieve the reporting without needing to parse the excluded dir