From c8b2b03f8a12ecada4740967b9d0a4abbcc03b30 Mon Sep 17 00:00:00 2001 From: eugene yokota Date: Sat, 14 Feb 2026 01:04:40 -0800 Subject: [PATCH] [1.x] Print warning about scala-reflect not found (#8736) **Problem** scala-reflect not found issue is confusing. **Solution** Print out a specialized warning message. --- .../sbt/internal/LibraryManagement.scala | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/main/src/main/scala/sbt/internal/LibraryManagement.scala b/main/src/main/scala/sbt/internal/LibraryManagement.scala index c50609ed8..a069eebbb 100644 --- a/main/src/main/scala/sbt/internal/LibraryManagement.scala +++ b/main/src/main/scala/sbt/internal/LibraryManagement.scala @@ -146,6 +146,11 @@ private[sbt] object LibraryManagement { .apply(updateInputs) if (isCached) markAsCached(report) else report } catch { + case r: ResolveException + if r.failed.exists(isMissingScalaLib) && + module.scalaModuleInfo.exists(_.scalaBinaryVersion == "2.13") => + informSandwich() + throw r case t @ (_: NullPointerException | _: OutOfMemoryError) => val resolvedAgain = resolve val culprit = t.getClass.getSimpleName @@ -160,6 +165,27 @@ private[sbt] object LibraryManagement { Tracked.inputChanged(cacheStoreFactory.make("inputs"))(doCachedResolve) } + def informSandwich(): Unit = { + log.warn("[sbt-8728] Smorrebrod - the end of Scala 2.13-3.x sandwich") + log.warn("") + log.warn("Scala 3.8+ cannot be used in a Scala 2.13 subproject.") + log.warn( + "Dependency resolution failed because scala-reflect or -compiler 3.x does not exist." + ) + log.warn( + "This happens when a Scala 2.13 subproject depends on Scala 3.8+ directly or transitively." + ) + log.warn("To fix this, either") + log.warn(" - Keep Scala 3 subproject or transitive dependency to 3.7 or below, or") + log.warn(" - Migrate the Scala 2.13 subproject to Scala 3.x") + log.warn("See https://github.com/sbt/sbt/discussions/8728") + } + + def isMissingScalaLib(m: ModuleID): Boolean = + m.organization == "org.scala-lang" && + (m.name == "scala-compiler" || m.name == "scala-reflect") && + (m.revision.startsWith("3.")) + // Get the handler to use and feed it in the inputs // This is lm-engine specific input hashed into Long val extraInputHash = module.extraInputHash