Skip to content

Bug: run --all fails to match dependencies in queue when symlinks are used #5502

@jean-mercier-hivebrite

Description

@jean-mercier-hivebrite

Bug: run --all fails to match dependencies in queue when symlinks are used

Describe the bug

When using terragrunt run --all apply with a symlinked directory, dependencies are not correctly matched to queue entries because paths are stored in incompatible formats:

  • Queue entries use relative paths: ./namespace
  • Dependencies use broken hybrid paths after symlink resolution: ../../../../../real/path/to/stacks/.../namespace

This causes all dependencies to be marked as "not in queue, considering it ready", resulting in all units running in parallel regardless of their actual dependencies.

Environment

  • Terragrunt version: v0.97.2
  • Terraform version: 1.14.3
  • OS: Linux (container)

Steps to reproduce

  1. Create a directory structure:
/app/
├── terraform/
│   └── stacks/
│       └── myproject/
│           ├── namespace/
│           │   └── terragrunt.hcl
│           ├── service-a/
│           │   └── terragrunt.hcl  # depends on namespace
│           └── service-b/
│               └── terragrunt.hcl  # depends on namespace
  1. Create a symlink to the terraform directory:
ln -s /app/terraform /terraform
  1. In the terragrunt.hcl files, use the symlink path for dependencies:
# service-a/terragrunt.hcl
dependency "namespace" {
  config_path = "/terraform/stacks/myproject/namespace"
}

inputs = {
  namespace = dependency.namespace.outputs.name
}
  1. Run terragrunt from the project directory:
cd /app/terraform/stacks/myproject
terragrunt run --all apply

Expected behavior

Dependencies should be correctly matched to queue entries regardless of symlink resolution. Units should run in dependency order:

  1. namespace runs first
  2. service-a and service-b wait for namespace to complete

Actual behavior

All units start simultaneously because dependencies are not matched in the queue.

Debug output shows the path mismatch:

Unit queue will be processed for apply in this order:
- Unit namespace
- Unit service-a
- Unit service-b

Runner Pool Controller: starting with 3 tasks, concurrency 2147483647

Dependency /app/terraform/stacks/myproject/namespace is not in queue, considering it ready

And when listing units with dependencies:

=> Unit service-a (excluded: false, assume applied: false, dependencies: [../../../../../app/terraform/stacks/myproject/namespace])
=> Unit service-b (excluded: false, assume applied: false, dependencies: [../../../../../app/terraform/stacks/myproject/namespace])
=> Unit namespace (excluded: false, assume applied: false, dependencies: [])

Notice:

  • Queue entries use: ./namespace
  • Dependencies use: ../../../../../app/terraform/stacks/myproject/namespace

The path comparison in entryByPathUnsafe fails:

// internal/queue/queue.go line ~193
func (q *Queue) entryByPathUnsafe(path string) *Entry {
    for _, entry := range q.Entries {
        if entry.Component.Path() == path {  // This comparison fails!
            return entry
        }
    }
    return nil
}

Root cause analysis

The issue appears to be in path normalization when symlinks are involved:

  1. config_path = "/terraform/stacks/.../namespace" is an absolute path through a symlink
  2. During discovery, filepath.EvalSymlinks() resolves this to /app/terraform/stacks/.../namespace
  3. This is then converted to a relative path using filepath.Rel() from the working directory
  4. The resulting path ../../../../../app/terraform/stacks/.../namespace is a broken hybrid (goes up then uses absolute path components)
  5. Queue entries are stored with simple relative paths like ./namespace
  6. The string comparison == fails because the formats don't match

Workaround

Use bind mounts instead of symlinks, or use the real absolute path in config_path instead of the symlinked path.

Additional context

This worked correctly in Terragrunt v0.93.x. The regression appears to be related to path handling changes in the v0.95+ releases.

Related issues that may share root cause:

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions