StackTraces
Spring Boot已驗證

Spring Boot 報 ConfigDataLocationNotFoundException

@debug_master27 天前更新閱讀 6 min00

從 Spring Boot 2.4 開始,設定處理機制由舊版的 ConfigFileApplicationListener 全面重構為 ConfigDataEnvironmentPostProcessor。若通過命令行、環境變數或 spring.profiles.active 指定了不存在的設定文件,或者使用 spring.config.import 引入了缺失的資源且未聲明 optional: 前綴,Spring Boot 啟動時將嚴格校驗並直接拋出 ConfigDataLocationNotFoundException。

Issue & Env(案發現場與環境)

在本地開發或 CI/CD 流水線中部署 Spring Boot 2.4+ / 3.x 應用時,指定環境 profile 或加載外部化掛載文件常遭遇容器無法拉起的問題:

  • 受影響版本:Spring Boot 2.4.0 ~ 3.3.x(引入 ConfigData 機制後的所有版本)
  • 運行時環境:OpenJDK 17 / 21,Docker / Kubernetes Pod / 本地 IDEA
  • 觸發條件:
    1. spring.profiles.active 指定的 profile 文件不存在(如筆誤或 .gitignore 漏傳)。
    2. 使用 spring.config.import 引用了掛載路徑,但在無該卷掛載的環境下未標明可選。

StackTrace(堆疊日誌)

控制台直接拋出例外並快速失敗終止 JVM,阻斷容器拉起:

2026-09-02 10:14:22.841 ERROR 1 --- [main] o.s.boot.SpringApplication : Application run failed

org.springframework.boot.context.config.ConfigDataLocationNotFoundException: Config data location 'classpath:/application-dev.yml' does not exist
    at org.springframework.boot.context.config.ConfigDataLocationNotFoundException.create(ConfigDataLocationNotFoundException.java:70)
    at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferences(StandardConfigDataLocationResolver.java:152)
    at org.springframework.boot.context.config.StandardConfigDataLocationResolver.resolve(StandardConfigDataLocationResolver.java:128)
    at org.springframework.boot.context.config.ConfigDataLocationResolvers.resolve(ConfigDataLocationResolvers.java:114)
    at org.springframework.boot.context.config.ConfigDataEnvironment.processInitial(ConfigDataEnvironment.java:240)
    at org.springframework.boot.context.config.ConfigDataEnvironment.processAndApply(ConfigDataEnvironment.java:198)
    at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:96)
    at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent(EnvironmentPostProcessorApplicationListener.java:109)
    at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEvent(EnvironmentPostProcessorApplicationListener.java:94)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:178)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:171)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:145)
    at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:85)
    at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:66)
    at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:344)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:302)
    at com.example.demo.DemoApplication.main(DemoApplication.java:12)

Reproduce(復現程式碼)

在 src/main/resources/ 下僅放置預設的 application.yml:

spring:
  application:
    name: order-service
  profiles:
    active: dev
  config:
    import:
      - "file:/etc/secrets/config.properties"

但項目中並沒有 application-dev.yml(可能因拼寫為 application-devel.yml,或構建工具排除),同時宿主機目錄 /etc/secrets/config.properties 不存在。

運行命令觸發構建與啟動:

mvn spring-boot:run

框架在引導階段觸發 ConfigDataLocationNotFoundException 並直接退出進程。

Root Cause(根因分析)

在 Spring Boot 2.4 之前,框架對缺失的 profile 設定文件預設採取靜默容忍策略,如果未找到 application-dev.yml,通常只是忽略該文件並繼續使用主設定。

自 Spring Boot 2.4 引入全新的 ConfigData API 起,底層由 StandardConfigDataLocationResolver 與 ConfigDataEnvironment 嚴格把關:

  1. 顯式指定被判定為強制依賴:當系統解析到顯式設定的激活環境(如 -Dspring.profiles.active=dev)或顯式引用的導入路徑(spring.config.import)時,框架判定開發者是有意加載該資源的。
  2. 缺乏可選標記(Optional Prefix):如果目標文件為非必選項(例如容器內可能存在也可能不存在的掛載卷),但設定中未加上 optional: 前綴,Spring Boot 會認為關鍵設定遺失。為了防止系統帶著半殘的設定啟動導致隱蔽的運行時災難,設計上選擇快速失敗(Fail-Fast)。
  3. 打包資源過濾:在多模塊 Maven / Gradle 工程中,resources 設定若未包含指定 profile 的文件名模式,導致 jar 包內實際缺失對應資源。

The Fix(解決方案)

方案 1:檢查 Profile 拼寫與構建資源打包

確認 src/main/resources 下的文件命名完全符合 application-{profile}.yml 或 application-{profile}.properties 規範。如果使用 Maven 構建,確認 pom.xml 中未誤排 YAML 文件:

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
                <include>application*.yml</include>
                <include>application*.properties</include>
            </includes>
        </resource>
    </resources>
</build>

方案 2:為外部導入路徑添加 optional 前綴

如果外部設定(如 K8s Secret、ConfigMap 卷或外部掛載文件)只在特定宿主機存在,必須使用 optional: 前綴進行聲明:

spring:
  config:
    import:
      - "optional:file:/etc/secrets/config.properties"
      - "optional:classpath:custom-config.yml"

增加 optional: 之後,StandardConfigDataLocationResolver 若探測到文件缺失,將跳過加載而不會拋出 ConfigDataLocationNotFoundException。

方案 3:使用 debug 模式排查實際生效路徑

在啟動參數中加入 --debug 選項:

java -jar target/demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev --debug

控制台會輸出完整的 ConditionsEvaluationReport 以及設定加載位置列表,明確標出當前掃描的 classpath 根目錄以及各設定源的來源文件路徑。

References(參考來源)

最後更新於 2026-09-14

這篇幫到你了嗎?

剛解決了一個棘手的報錯?花兩分鐘記錄下來,幫助下一個遇到同樣問題的開發者。

貢獻一條解法