locals breaks stack listing when name_template vars come from parent imports
- Dominant language
- Go
- Stars
- 1.4k
- Forks
- 175
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 134
Description
### Describe the Bug
## What's broken
`internal/exec/describe_locals.go:deriveStackNameFromTemplate` renders `name_template` using only the current file's `vars:` block — ancestor `_defaults.yaml` imports are NOT merged:
```go
// internal/exec/describe_locals.go (lines ~513–518)
templateData := map[string]any{
"vars": varsSection, // ← current file only, no import merge
}
stackName, err := ProcessTmpl(atmosConfig, "describe-locals-name-template", atmosConfig.Stacks.NameTemplate, templateData, false)
```
In hierarchical `_defaults` layouts (which Atmos docs recommend), identity vars like `namespace`/`tenant`/`stage` live in parent imports. The pre-pass renders `name_template` with those vars missing, producing a malformed name (e.g. `-prod`). The real stack (e.g. `acme-prod`) then disappears from `atmos list stacks`, a
nd `atmos describe component -s acme-prod` fails with "invalid component".
Every existing fixture under `tests/fixtures/scenarios/locals-*` sets identity vars directly in the leaf stack file, so none exercise this path.
## Minimal repro
File tree:
```
repro/
├── atmos.yaml
├── components/terraform/mock/main.tf # empty file
└── stacks/
└── orgs/
├── _defaults.yaml
└── prod.yaml
```
`atmos.yaml`:
```yaml
base_path: "./"
components:
terraform:
base_path: "components/terraform"
stacks:
base_path: "stacks"
included_paths: ["orgs/**/*"]
excluded_paths: ["**/_defaults.yaml"]
name_template: "{{ .vars.namespace }}-{{ .vars.stage }}"
templates:
settings:
enabled: true
```
`stacks/orgs/_defaults.yaml`:
```yaml
vars:
namespace: acme
```
`stacks/orgs/prod.yaml`:
```yaml
import: [./_defaults]
vars:
stage: prod
locals:
foo: bar # any locals block is enough to trigger the bug
components:
terraform:
vpc:
metadata: {component: mock}
vars: {name: "{{ .locals.foo }}"}
```
## Expected vs actual
```
$ atmos list stacks
expected: acme-prod
actual: -prod ← namespace missing, stack unfindable
$ atmos describe component vpc -s acme-prod
expected: describes vpc in acme-prod
actual: Error: invalid component … Could not find the component vpc in the stack acme-prod
```
Remove the `locals:` block and `acme-prod` appears correctly — proving the issue is specific to the locals pre-pass code path.
## Affected versions
Reproduced on v1.216.0. Likely present since file-scoped locals landed (v1.200+).
## Related
- Related to prior work on locals + stack context: #2080, see `docs/fixes/2026-03-15-locals-terraform-state-missing-stack-context.md`.
- Cross-linked sibling issues:
- Performance: N² evaluation of `!terraform.state` in locals during `list stacks` — #2344
- Config: `describe-stacks-name-template` ignores global `ignore_missing_template_values` — #2345
Contributor guide
Research direction
Start in internal/exec/describe_locals.go at deriveStackNameFromTemplate and inspect how imported _defaults.yaml vars are handled before ProcessTmpl runs. Add a fixture under tests/fixtures/scenarios/locals-* based on the namespace and stage repro, then run the relevant locals tests and verify that atmos list stacks shows acme-prod and describe component vpc -s acme-prod succeeds.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, terraform
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100