In a project with multiple main classes, the "multiple main classes detected" warning is unwanted noise when running tests. This message is already suppressed for explicit run commands, now also suppress it for test.
**Problem**
In an Ivy resolver pattern, the [organisation]/[organization] token has its dots rewritten to slashes (org.example → org/example), behaving like Ivy's [orgPath] token rather than being literal. Per the [Apache Ivy spec](http://ant.apache.org/ivy/history/latest-milestone/concept.html), [organisation] should be substituted literally and [orgPath] is the slash-separated form.
Root cause: Patterns.isMavenCompatible defaulted to true, which sbt forwards to Apache Ivy as setM2compatible(true); with m2-compatibility on, Ivy rewrites the [organisation] token to slash form. A user supplying a custom Ivy pattern (e.g. for an SFTP/SSH resolver) inherited that default and got the wrong paths, with no obvious indication why. The only workaround was the non-obvious withIsMavenCompatible(false).
**Solution**
Flip the default of Patterns.isMavenCompatible from true to false, so a hand-written Patterns keeps [organisation] literal by default — matching the Ivy spec.
Building on #9270 (which parallelized resolution in non-interactive runs by
narrowing the lm-coursier lock to only fire while coursier renders its
interactive progress bar), this makes `update` resolve in parallel under the
interactive super shell as well.
Count distinct non-checksum urls instead and drop the module claim.
Report the elapsed time of the current burst so the super shell renders
a live counter rather than a frozen "0s". Tests now encode coursier's
per-session call pattern.
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
**Problem**
console / javaOptions is ignored.
**Solution**
1. This enables forked console even for sbt --server mode.
2. This includes console / javaOptions to the forkOptions.
**Problem**
Chunked upload/download doesn't work.
**Solution**
1. This fixes the SERVICE_NAME shading.
2. This fixes the resource name.
3. This fixes download stream processing.
**Problem**
We can get into a situation where CompileInputs2 become identical for Scala 3.x and 2.13, which breaks the recovery of Zinc analysis.
**Solution**
This includes Scala version into CompileInput2 to workaround this issue.
**Problem**
BatchUpdateBlobsRequest suffers from gRPC's message size limitation.
**Solution**
For larger files, we switch to using the ByteStream API, chunked to 1MB at a time.
**Problem**
Platform suffix is absent in published artifacts.
#9118 partially solved this. It didn't touch publish-side naming though, so the published files still drop the suffix in three places.
**Solution**
This fixes
- ivyless publication names - CoursierArtifactsTasks.coursierPublicationsTask
- ivyless POM <artifactId> (the coordinate written inside the .pom) - PomGenerator.crossVersionDep
- Ivy backend (useIvy := true) - CrossVersion.substituteCross via IvyActions
When a file referenced by a task's inputs/outputs (e.g. Compile / resources +=
file("nope.txt")) does not exist, hashing the task's cache key threw a
NoSuchFileException deep inside sjsonnew serialization. It surfaced as an opaque
sjsonnew.SerializationException that dumped the entire input list, with the real
cause buried several `Caused by:` levels down, so users routinely mistook it for
a corrupt cache and reached for `clean`.
ActionCache.mkInput now catches the hashing failure, detects a NoSuchFileException
anywhere in the cause chain (ActionCache.findMissingFile), and throws a
MessageOnlyException naming the file:
[error] file referenced by the build does not exist: nope.txt
util-cache gains a dependency on util-control (a leaf module, no cycle) for
MessageOnlyException.
Fixes#9217.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
update held a process-global lock around coursier resolution and artifact
fetching whenever a logger was set OR coursier was not in fallback mode. That
lock exists only to serialize coursier's interactive progress bar, which is
rendered solely when no custom logger is supplied and coursier is not in
fallback mode. The loggerOpt.nonEmpty clause therefore over-serialized the
common non-interactive case (IntelliJ re-imports, CI, any non-TTY run, where
sbt supplies a quiet debug-only logger), making update scale with the number
of modules rather than the number of distinct artifacts.
Fixes#5508.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deduplicate executable jar package entries. In the issue, the duplicate was something like:
(resource_managed/.../sbt/sbt.autoplugins, "sbt/sbt.autoplugins")
(classes/.../sbt/sbt.autoplugins, "sbt/sbt.autoplugins")
This is because copyResources copied autoplugin metadata to the classes directory.
Solution: when composing the packageBinMappings, differentiate between artifacts that come from class directory and from outside of it. If there is a duplicate, prefer resource that comes from outside of it.
The original fixture pinned
scalaOrganization := "io.github.scala-wasm"
scalaVersion := "3.8.3-RC1-wasm-bin-SNAPSHOT"
and ran compile. The wasm fork never published a release of
scala3-library_3 -- only a snapshot to Sonatype's central-snapshots
repo, which has ~90-day retention. #8732 merged 2026-02-21; the
snapshot was GC'd ~2026-05-22 and develop CI began failing
deterministically.
Fixes#9259.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fixes#9009.
dependencyMode := DependencyMode.PlusOne strips every internal
project dependency from the compile classpath, even direct ones --
LibA/compile fails with Not found: CoreClass despite
LibA.dependsOn(Core). Direct mode happens to work today, but only by
accident (filterByDirectDeps matches against allDependencies, which
includes projectDependencies -- the bug surface is one step removed).
Root cause: ClasspathImpl.filterByPlusOne resolves the
direct-dep key set from UpdateReport, which only contains externally
resolved (LM) modules. Internal project refs never appear there, so
resolvedDirectKeys is empty for internal entries; plusOneKeys is
likewise empty; the final filter strips every internal classpath
entry whose moduleIDStr identifies an internal project. Diagnosis on
the issue by eureka0928.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fixes#6886.
dependencyTree, dependencyBrowseTree, and inspect tree re-explore
the same node once per incoming edge. In a DAG with N levels and M
children per node the rendered output is O(M^N) -- the OP needed
>16 GB heap, #7360 has a 6 GB heap dump, and Friendseeker's analysis
on the issue showed the exponential re-traversal directly.
Fix: track a visited set across the renderer's recursion. The first
time a node is encountered it is rendered in full; on subsequent
visits the entry collapses to a one-line +- <id> (*) (ASCII) or a
<id> (*) leaf (JSON), matching Maven's dependency:tree (*)
convention. Cycle detection (separate parents set, (cycle) marker)
is unchanged.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>