dependabot / dependabot/dependabot-core
[terraform] SystemStackError ("stack level too deep") in FileFetcher when ecosystem is configured with multi-directory `directories:`
- 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
Assessment
This issue has not been assessed yet.