Scala项目执行sbt dist/Docker发布时遇Unpickling错误
Scala 3项目Docker化/打包时出现DottyDoc反序列化错误
我开发的Scala 3项目本地编译运行完全正常,但在尝试Docker化部署、执行sbt dist或sbt assembly时遇到反序列化(unpickling)相关错误,本地运行无此问题。错误触发场景包括:
- 执行
sbt dist - 执行
sbt assembly - 执行
Docker publishLocal
错误日志(执行sbt dist时)
[info] Wrote /Users/kabir/development/chanja/payment/target/scala-3.3.0/payment_3-0.1.0.pom [info] Main Scala API documentation to /Users/kabir/development/chanja/payment/target/scala-3.3.0/api... [info] Skipping unused scalacOptions: -Xmax-inlines [error] class models.infrastructure.org.thirty7.payment.payment cannot be unpickled because no class file was found for denot: val <none> [error] class models.infrastructure.org.thirty7.payment.wallet cannot be unpickled because no class file was found for denot: val <none> [error] two errors found [error] (Compile / doc) DottyDoc Compilation Failed [error] Total time: 9 s, completed 16-Oct-2023 02:12:49
build.sbt 配置
ThisBuild / scalaVersion := "3.3.0" ThisBuild / version := "0.1.0" ThisBuild / organization := "org.thirty7.payment" ThisBuild / organizationName := "thirty7" ThisBuild / name := "payment" //addCompilerPlugin("com.hmemcpy" %% "zio-clippy" % "0.0.2") enablePlugins(JavaAppPackaging) enablePlugins(DockerPlugin) Test / fork := true //fork / run := true assemblyJarName / assembly := file("payment.jar") ThisBuild / assemblyMergeStrategy := { case PathList("javax", "servlet", _*) => MergeStrategy.first case PathList(_*) => MergeStrategy.discard case "application.conf" => MergeStrategy.concat case "unwanted.txt" => MergeStrategy.discard case x => val oldStrategy = (ThisBuild / assemblyMergeStrategy).value oldStrategy(x) // case "module-info.class" => MergeStrategy.discard // case PathList("META-INF", // _*) => MergeStrategy.discard // case x => // val oldStrategy = (assembly / assemblyMergeStrategy).value // oldStrategy(x) } lazy val root = (project in file(".")) .settings( name := "payment" ) scalacOptions ++= Seq("-Xmax-inlines", "75") libraryDependencies ++= { val nscalaTimeVersion = "2.32.0" val scalaBcryptVersion = "4.3.0" val postgresqlVersion = "42.5.4" val quillVersion = "4.6.0.1" val flywayVersion = "9.16.0" val zioVersion = "2.0.13" val zioKafkaVersion = "2.3.2" val zioSchemaVersion = "0.4.8" val zioJsonVersion = "0.4.2" val zioJsonJwtVersion = "9.2.0" val zioConfigVersion = "3.0.7" val zioHttpVersion = "0.0.5" val zioLoggingVersion = "2.1.11" val testContainersVersion = "0.10.0" Seq( "com.github.nscala-time" %% "nscala-time" % nscalaTimeVersion, "com.github.jwt-scala" %% "jwt-zio-json" % zioJsonJwtVersion, "io.getquill" %% "quill-jdbc-zio" % quillVersion, "org.flywaydb" % "flyway-core" % flywayVersion, "org.postgresql" % "postgresql" % postgresqlVersion, "dev.zio" %% "zio" % zioVersion, "dev.zio" %% "zio-kafka" % zioKafkaVersion, "dev.zio" %% "zio-schema" % zioSchemaVersion, "dev.zio" %% "zio-http" % zioHttpVersion, "dev.zio" %% "zio-json" % zioJsonVersion, "dev.zio" %% "zio-config" % zioConfigVersion, "dev.zio" %% "zio-config-typesafe" % zioConfigVersion, "dev.zio" %% "zio-config-magnolia" % zioConfigVersion, "dev.zio" %% "zio-logging-slf4j-bridge" % zioLoggingVersion, "dev.zio" %% "zio-test" % zioVersion % Test, "dev.zio" %% "zio-test-sbt" % zioVersion % Test, "dev.zio" %% "zio-test-magnolia" % zioVersion % Test, // "io.github.embeddedkafka" %% "embedded-kafka" % "3.5.1", // ("io.github.embeddedkafka" %% "embedded-kafka" % "3.5.1" % Test) // ("dev.zio" %% "zio-kafka-testkit" % zioKafkaVersion % Test) "io.github.scottweaver" %% "zio-2-0-testcontainers-postgresql" % testContainersVersion % Test, "io.github.scottweaver" %% "zio-2-0-testcontainers-kafka" % testContainersVersion % Test, "io.github.scottweaver" %% "zio-2-0-db-migration-aspect" % testContainersVersion % Test // "dev.zio" %% "zio-logging" % "2.1.0", // "dev.zio" %% "zio-logging-slf4j" % "2.1.0", // "org.slf4j" % "slf4j-log4j12" % "1.7.36", ) } testFrameworks += new TestFramework("zio.test.sbt.ZTestFramework")
plugins.sbt 配置
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.9.16") addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.3")
解决方法尝试
1. 跳过文档编译
错误来自DottyDoc(Scala 3的文档生成工具),打包/部署无需强制生成API文档。临时跳过可执行:
sbt dist skipCompileDoc # sbt assembly同理 sbt assembly skipCompileDoc
永久禁用文档编译,在build.sbt中添加:
Compile / doc / skip := true
2. 修正类命名与包结构
错误中的payment、wallet类名是小写,虽然Scala允许,但可能导致DottyDoc解析异常。建议改为大驼峰命名(如Payment、Wallet),同时检查包结构与文件路径是否一致。
3. 修复assembly合并策略
当前策略中case PathList(_*) => MergeStrategy.discard会丢弃几乎所有文件,这是错误的,应删除该规则,保留核心类文件:
ThisBuild / assemblyMergeStrategy := { case PathList("javax", "servlet", _*) => MergeStrategy.first case "application.conf" => MergeStrategy.concat case "unwanted.txt" => MergeStrategy.discard case x => val oldStrategy = (ThisBuild / assemblyMergeStrategy).value oldStrategy(x) }
4. 更新依赖版本
Scala 3.3.0可能存在DottyDoc已知bug,尝试升级到最新稳定版(如3.3.1+),同时更新插件版本:
- sbt-native-packager 升级到1.10.0+
- sbt-assembly 升级到2.1.5+
内容的提问来源于stack exchange,提问作者khalilkm01
相关产品推荐
相关产品推荐

