dependabot / dependabot/dependabot-core

[terraform] SystemStackError ("stack level too deep") in FileFetcher when ecosystem is configured with multi-directory `directories:`

Open
#15,097 2 comments 0 reactions 1 assignee Claimed by @markhallen View on GitHub
L: ruby:bundler L: terraform
Dominant language
Ruby
Stars
5.8k
Forks
1.5k
Avg merge
2d 18h
Merged PRs (30d)
149

Description

### Summary

The Terraform ecosystem updater crashes deterministically with a `SystemStackError` in `Pathname#cleanpath_aggressive` when `dependabot.yml` configures the ecosystem with the multi-directory `directories:` array. The crash happens before any update can be attempted, so the entire scheduled run aborts and no PRs are opened or refreshed.

Reproduced on two consecutive scheduled runs (~24h apart) with identical stack traces, so it is not flake.

### Repository / config

Reproducing config shape (private repo; names redacted but structure preserved — 8 sibling directories, each containing a `versions.tf` with a `required_providers` block):

```yaml
- package-ecosystem: "terraform"
directories:
- "/dir-a"
- "/dir-b"
- "/dir-c"
- "/dir-d"
- "/dir-e"
- "/dir-f"
- "/dir-g"
- "/dir-h"
schedule:
interval: "daily"
open-pull-requests-limit: 10
groups:
minor-and-patch:
update-types: ["minor", "patch"]
major:
update-types: ["major"]
```

Provider pinned in every directory: `hashicorp/aws ~> 6.43`. Several refresh PRs from a prior successful run are present in `existing-pull-requests` in the failing job's input.

### Updater image

`ghcr.io/dependabot/dependabot-updater-terraform:6c1cb3b6ece05d44a694c4ca2b6a7d118df9536b`
Proxy: `ghcr.io/dependabot/proxy:v2.0.20260427232629@sha256:4b22239a…`

### Stack trace

```
updater | /usr/local/lib/ruby/3.4.0/pathname.rb:128:in 'Kernel#initialize_dup': stack level too deep (SystemStackError)
from /usr/local/lib/ruby/3.4.0/pathname.rb:128:in 'Pathname#initialize'
from /usr/local/lib/ruby/3.4.0/pathname.rb:128:in 'Class#new'
from /usr/local/lib/ruby/3.4.0/pathname.rb:128:in 'Pathname#cleanpath_aggressive'
from /usr/local/lib/ruby/3.4.0/pathname.rb:98:in 'Pathname#cleanpath'
from /home/dependabot/common/lib/dependabot/file_fetchers/base.rb:170:in 'Dependabot::FileFetchers::Base#directory'
from /home/dependabot/dependabot-updater/vendor/ruby/3.4.0/gems/sorbet-runtime-0.6.13208/lib/types/private/methods/call_validation_2_7.rb:59:in 'UnboundMethod#bind_call'
from /home/dependabot/dependabot-updater/vendor/ruby/3.4.0/gems/sorbet-runtime-0.6.13208/lib/types/private/methods/call_validation_2_7.rb:59:in 'block in Dependabot::FileFetchers::Base#create_validator_method_fast0'
from /home/dependabot/common/lib/dependabot/file_fetchers/base.rb:268:in 'Dependabot::FileFetchers::Base#load_cloned_file_if_present'
... 9784 levels...
from bin/update_files.rb:41:in ''
```

### Two reproductions with identical signature

Two consecutive scheduled runs, ~24h apart (2026-05-20 and 2026-05-21). No config or repo-content changes between them; both ran the same `update_files` command on the same input and crashed at the same frame. Full logs available on request — they live in a private repo so direct links are not useful here.

### What I think is happening

`FileFetchers::Base#directory` (`base.rb:170`) ends up invoking `Pathname#cleanpath` on something that resolves through `cleanpath_aggressive` into an infinite `Pathname.new(self.dup)` chain — `initialize_dup` re-enters `cleanpath_aggressive` and the recursion never bottoms out. The "9784 levels" frame count is exactly the Ruby default stack depth, not a finite repetition.

The sorbet-runtime call-validation wrapping in the trace suggests the multi-directory branch added by [#7547 (cross-directory grouped updates)](https://github.com/dependabot/dependabot-core/pull/7547) is calling `directory` through a code path that the older single-`directory:` form doesn't take.

### What unblocks us locally

Splitting the one `package-ecosystem: terraform` block with `directories:` (plural) into N separate blocks with `directory:` (singular, the legacy form) is the obvious workaround. We haven't tried it yet because the repetition cost (groups, schedules, etc. all duplicated N×) is significant; happy to apply it if you confirm that's the recommended escape hatch while the underlying crash is being investigated.

### Asks

1. Is this a known shape of crash on the Terraform updater? Couldn't find a matching issue under `cleanpath_aggressive` / `SystemStackError` / `directories` on this repo.
2. Is the legacy single-`directory:` per-block split the right workaround?

Happy to provide additional logs or test patches against the updater image.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.