Repository navigation
Volta extends resolution in getNodeVersionFromFile has no cycle detection, recursing until stack overflow #1628
Description
Summary
getNodeVersionFromFile follows Volta extends recursively with no cycle detection, so a self-referential or mutually-referential volta.extends chain causes unbounded recursion and crashes the action with a stack overflow instead of a clear error.
Location
- File:
src/util.ts - Function:
getNodeVersionFromFile(versionFilePath: string) - Code path:
if (manifest.volta?.extends) {
const extendedFilePath = path.resolve(
path.dirname(versionFilePath),
manifest.volta.extends
);
core.info('Resolving node version from ' + extendedFilePath);
return getNodeVersionFromFile(extendedFilePath);
}No visited-path set or depth limit is threaded through the recursion.
Problem
Volta workspaces support {"volta": {"extends": "./base/package.json"}}. If the target (transitively) points back to a file already on the resolution stack — e.g. package.json with "extends": "./package.json" (typo), or a.json → b.json → a.json — the function recurses forever until V8 throws RangeError: Maximum call stack size exceeded. The user gets an opaque stack-overflow failure rather than a diagnostic naming the cycle.
Trigger / Reproduction
Based on static analysis (no workflow run performed):
- Set
node-version-fileto apackage.jsoncontaining:or a two-file cycle{"volta": {"extends": "./package.json"}}a.json↔b.jsonviavolta.extends. - Run the action.
getNodeVersionFromFileresolvesextends, re-enters itself with the same path, and never terminates normally.
Note: this is a static-analysis finding; I did not execute a workflow against a cyclic fixture.
Expected Behavior
Cyclic volta.extends should fail fast with a clear error naming the files in the cycle (e.g. Detected cyclic volta.extends: a.json -> b.json -> a.json), consistent with how missing files already throw The specified node version file at: ... does not exist.
Actual Behavior
Unbounded recursion until stack exhaustion, producing an unactionable RangeError with no mention of the offending extends chain.
Impact
- A one-character typo in
volta.extendsturns a configuration mistake into an opaque action crash, costing debugging time. - No data-loss risk, but the failure mode hides the actual cause (cycle) behind a generic engine error.
Suggested Direction
- Thread a
seen: Set<string>(resolved absolute paths) throughgetNodeVersionFromFile, checking before recursing and throwing a descriptive cycle error. Alternatively cap recursion depth with the same diagnostic. Either preserves current behavior for acyclic chains.
Evidence
- Source via API:
src/util.tsVolta-extends branch shows direct unconditional recursion with no guard; neighboring branches (missing file, non-JSON/TOML fallthrough) all have explicit handling, highlighting the gap. - Duplicate check: issue search for
volta extends cycle recursionreturnstotal_count: 0, and the open-issue list contains no extends-cycle report (nearest is.nvmrccomment parsing) — no apparent duplicate.
What happened
Unbounded recursion on cyclic Volta extends as detailed above.
Expected behavior
Fast, descriptive cycle error instead of stack overflow.
Steps to reproduce
Point node-version-file at a self- or mutually-referential Volta extends fixture and observe getNodeVersionFromFile re-enter indefinitely (static path; runtime stack overflow implied).
reproducible code
// package.json
{"volta": {"extends": "./package.json"}}- uses: actions/setup-node@v4
with:
node-version-file: package.jsonmanifest.yaml
N/A
Versions
- actions/setup-node: current
main(verified via API,src/util.ts) - Node: N/A (static analysis finding)
Classification
- FACT: Volta
extendsrecursion has no visited-set or depth cap (verified in source via API). - INFERENCE: cyclic fixtures therefore recurse until stack exhaustion.
- HYPOTHESIS: a visited-path guard produces a clear error with no change to valid chains.
Activity
v-priya-kinthali commentedon Sep 11, 2026
Hello @krishna3554👋,
Thank you for reporting this issue. We will investigate it and get back to you as soon as we have some feedback.
z0rimo commentedon Sep 14, 2026
I noticed this is assigned already. Are you actively working on a fix?
If not, I'd be happy to take it and add regression coverage for self-referential and multi-file volta.extends cycles.
v-gowridurgad commentedon Sep 21, 2026
Hi @z0rimo We’re actively working on this and will share an update once we have progress to report.
fix: detect cyclic volta.extends chains in node-version-file resolution