[2.x] fix: Skip Conflict when dependency relocations form a cycle#8919
Merged
eed3si9n merged 3 commits intosbt:developfrom Mar 19, 2026
Merged
[2.x] fix: Skip Conflict when dependency relocations form a cycle#8919eed3si9n merged 3 commits intosbt:developfrom
eed3si9n merged 3 commits intosbt:developfrom
Conversation
…ite) **Problem** Coursier graph.Conflict -> DependencyTree relocation can loop forever when Maven/Gradle relocation metadata forms a cycle (sbt-site 1.4.1, sbt#8917). **Solution** Detect relocation cycles with the same step logic as Coursier, skip Conflict for affected configs, log once per update. Generated-by: Claude
Contributor
Author
|
@eed3si9n Ready for review! |
Member
|
Thanks for identifying the root cause. Could you share your findings on coursier/coursier#3578 to help Coursier folks fix the issue as well? |
Contributor
Author
Posted a summary on coursier/coursier#3578 for upstream fix (cycle detection in |
eed3si9n
reviewed
Mar 18, 2026
lm-coursier/src/main/scala/lmcoursier/internal/RelocationCycleDetector.scala
Outdated
Show resolved
Hide resolved
eed3si9n
reviewed
Mar 18, 2026
lm-coursier/src/main/scala/lmcoursier/internal/RelocationCycleDetector.scala
Outdated
Show resolved
Hide resolved
Member
Contributor
Author
|
Thank you. |
eed3si9n
approved these changes
Mar 19, 2026
eed3si9n
pushed a commit
to eed3si9n/sbt
that referenced
this pull request
Mar 23, 2026
…t#8919) **Problem** Coursier graph.Conflict -> DependencyTree relocation can loop forever when Maven/Gradle relocation metadata forms a cycle (sbt-site 1.4.1). **Solution** Detect relocation cycles with the same step logic as Coursier, skip Conflict for affected configs, log once per update. Generated-by: Claude
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #8924
Problem
sbt 1.12.6+ (and sbt 2.x with Coursier 2.1.25-M24) hangs indefinitely on
updatefor projects usingaddSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.4.1"). The JVM stays in a tight loop; Ctrl+C often does not stop it (see #8917).Root Cause
After resolution succeeds,
SbtUpdateReportcallscoursier.graph.Conflict(resolution), which buildsDependencyTreenodes. Each node’srelocationhelper follows Maven/Gradle relocation metadata with tail recursion but no cycle detection. For sbt-site’s graph, relocation chains revisit the same coordinates, sorelocationnever terminates (coursier#3578).Solution
Add
RelocationCycleDetector, which performs the same single relocation step as Coursier’sDependencyTree.Node.relocationand walks the implied graph. If any relocation chain would revisit a node, we skipcoursier.graph.Conflictfor affected configurations (resolution and artifacts are unchanged). One warning per update lists affected configuration names.Alternatives considered: (1) bump Coursier to an unreleased fixed version — not available on Maven Central; (2) timeout around
Conflict— nondeterministic and hides real errors; (3) vendor patchedDependencyTree— would not affectConflictin the coursier JAR (same-artifact linkage).Testing
RelocationCycleDetectorSpec: incomplete resolution is not flagged as cyclic.ResolutionSpecproperty resolve sbt-site 1.4.1 (sbt sbt 1.12.6 gets stuck trying to resolve sbt-site 1.4.1 #8917): same resolution path as the reported bug; completes in bounded time with a non-empty classpath.Verify:
./sbt "lmCoursier/testOnly lmcoursier.ResolutionSpec -- -z \"sbt-site\"" ./sbt lmCoursier/testBefore / After
updateon sbt-site never finishes (infinite relocation expansion insideConflict).Edge Cases Handled
relocation.DependencyTree.missingOk: existingtry/catchunchanged.