You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 08:51:06