From 727f4b05c6eb31a7365a6d86ab7feb37941ccbb2 Mon Sep 17 00:00:00 2001 From: Match <132382032+gayanMatch@users.noreply.github.com> Date: Tue, 13 Jan 2026 15:45:16 -0800 Subject: [PATCH] fix: Fix NoClassDefFoundError after changing val in build.sbt (#8521) **Problem** When a val definition in build.sbt changes and the user runs `reload`, sbt crashes with `NoClassDefFoundError: $Wrap$`. ``` java.lang.NoClassDefFoundError: $Wrape8743d4f36$ at $Wrap0b8ea34d40$.$anonfun$1(build.sbt:1) ``` The workaround was to delete `project/target` directory. **Solution** The root cause was that imports were not included in the hash calculation when evaluating build.sbt expressions. When a val definition changes: 1. Its `$Wrap` module gets a new hash 2. Settings that reference the val get new imports pointing to the new module 3. But if the setting expression didn't change, its hash was the same 4. The old cached class was loaded with bytecode referencing the old module Fix: Include imports in the hash calculation in `Eval.evalCommon`. Also re-enable `cleanEvalClasses` in `Load.scala` which was disabled pending this fix. --- buildfile/src/main/scala/sbt/internal/Eval.scala | 4 ++++ main/src/main/scala/sbt/internal/Load.scala | 8 +++----- sbt-app/src/sbt-test/project/reload-val-change/build.sbt | 2 ++ .../sbt-test/project/reload-val-change/changes/build.sbt | 2 ++ sbt-app/src/sbt-test/project/reload-val-change/test | 5 +++++ 5 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 sbt-app/src/sbt-test/project/reload-val-change/build.sbt create mode 100644 sbt-app/src/sbt-test/project/reload-val-change/changes/build.sbt create mode 100644 sbt-app/src/sbt-test/project/reload-val-change/test diff --git a/buildfile/src/main/scala/sbt/internal/Eval.scala b/buildfile/src/main/scala/sbt/internal/Eval.scala index 92c0f2d58..c030cb8cf 100644 --- a/buildfile/src/main/scala/sbt/internal/Eval.scala +++ b/buildfile/src/main/scala/sbt/internal/Eval.scala @@ -216,6 +216,10 @@ class Eval( digester.update(bytes(ev.extraHash)) // Include SNAPSHOT classpath hash to invalidate cache when sbt version changes (fixes #7713) digester.update(bytes(snapshotClasspathHash)) + // Include imports in hash to invalidate cache when definition module names change (fixes #7424) + imports.strings.foreach { imp => + digester.update(bytes(imp)) + } val d = digester.digest() val hash = Hash.toHex(d) val moduleName = makeModuleName(hash) diff --git a/main/src/main/scala/sbt/internal/Load.scala b/main/src/main/scala/sbt/internal/Load.scala index a5e77f546..0d6b83a00 100755 --- a/main/src/main/scala/sbt/internal/Load.scala +++ b/main/src/main/scala/sbt/internal/Load.scala @@ -866,11 +866,9 @@ private[sbt] object Load { ) } val loadedProjects = processAutoAggregate(loadedProjects0, uri) - // TODO: Uncomment when we fixed https://github.com/sbt/sbt/issues/7424 - // likely keepClassFiles isn't covering enough. - // timed("Load.loadUnit: cleanEvalClasses", log) { - // cleanEvalClasses(defDir, keepClassFiles) - // } + timed("Load.loadUnit: cleanEvalClasses", log) { + cleanEvalClasses(defDir, keepClassFiles) + } val defs = if (defsScala.isEmpty) defaultBuildIfNone :: Nil else defsScala // HERE we pull out the defined vals from memoSettings and unify them all so // we can use them later. diff --git a/sbt-app/src/sbt-test/project/reload-val-change/build.sbt b/sbt-app/src/sbt-test/project/reload-val-change/build.sbt new file mode 100644 index 000000000..b2c4d0730 --- /dev/null +++ b/sbt-app/src/sbt-test/project/reload-val-change/build.sbt @@ -0,0 +1,2 @@ +val myVersion = "1.0.0" +name := myVersion diff --git a/sbt-app/src/sbt-test/project/reload-val-change/changes/build.sbt b/sbt-app/src/sbt-test/project/reload-val-change/changes/build.sbt new file mode 100644 index 000000000..be006535c --- /dev/null +++ b/sbt-app/src/sbt-test/project/reload-val-change/changes/build.sbt @@ -0,0 +1,2 @@ +val myVersion = "2.0.0" +name := myVersion diff --git a/sbt-app/src/sbt-test/project/reload-val-change/test b/sbt-app/src/sbt-test/project/reload-val-change/test new file mode 100644 index 000000000..00cc61e01 --- /dev/null +++ b/sbt-app/src/sbt-test/project/reload-val-change/test @@ -0,0 +1,5 @@ +# https://github.com/sbt/sbt/issues/7424 +> name +$ copy-file changes/build.sbt build.sbt +> reload +> name