Scala Typesafe Config解析异常:Docker部署时无分号却报错
排查Typesafe Config打包后解析异常问题
问题核心
使用Scala 2.13.16 + com.typesafe:config 1.4.3,本地运行application.conf完全正常,但通过sbt clean; assembly打包后用Docker Compose部署时,出现解析错误:
com.typesafe.config.ConfigException$Parse: application.conf @ jar:file:/app/app.jar!/application.conf: 6: Key ';' may not be followed by token: '}' (if you intended '}' to be part of a key or string value, try enclosing the key or value in double quotes)
你的配置文件本身没有分号,且assembly合并策略设置为MergeStrategy.concat。
根因分析
本地运行时,Typesafe Config会自动处理类路径中多个application.conf的合并逻辑,它会按语法规则解析每个独立的配置文件,不会出现拼接错误。
但sbt assembly的MergeStrategy.concat是直接将所有依赖包中的application.conf内容字符串拼接成一个文件,如果某个依赖的application.conf末尾没有换行,或者以分号结尾,就会导致你的配置内容和其他配置的内容连在一起,形成非法的HOCON语法。比如:
- 某个依赖的配置最后一行是
some.config = value; - 拼接后你的配置的最后一行
}会直接接在分号后面,变成;} - HOCON解析器会把
;误认为是一个key,从而抛出"Key ';' may not be followed by token: '}'"的错误
解决方案
方案1:优先使用项目自身的application.conf
如果你的项目配置不需要依赖其他包的application.conf,直接改用MergeStrategy.first,只保留你自己的配置文件:
assemblyMergeStrategy in assembly := { case PathList("application.conf") => MergeStrategy.first case other => val defaultStrategy = (assemblyMergeStrategy in assembly).value defaultStrategy(other) }
方案2:自定义带换行的合并策略
如果需要保留多个配置文件的内容,自定义一个合并策略,确保每个配置文件之间添加换行,避免内容粘连:
import sbt._ import sbtassembly._ val concatWithNewlines = new MergeStrategy { val name = "concatWithNewlines" def apply(tempDir: File, path: String, files: Seq[File]): Either[String, Seq[(File, String)]] = { val mergedContent = files.map(IO.read).mkString("\n\n") // 用两个换行分隔不同配置文件 val tempFile = File.createTempFile("merged-application", ".conf", tempDir) IO.write(tempFile, mergedContent) Right(Seq(tempFile -> path)) } } assemblyMergeStrategy in assembly := { case PathList("application.conf") => concatWithNewlines case other => val defaultStrategy = (assemblyMergeStrategy in assembly).value defaultStrategy(other) }
方案3:排查并修复依赖的配置文件(不推荐)
逐一检查所有依赖包中的application.conf,找出末尾有分号或无换行的文件,手动修改后重新打包。但这种方式维护成本极高,不建议采用。
内容的提问来源于stack exchange,提问作者Jelly
相关产品推荐
相关产品推荐

