Repository navigation
Description
Summary
Running the tools jarmode extract command against an executable Spring Boot WAR fails with IllegalStateException: Invalid library location WEB-INF/lib-provided/.... The extractor assumes every entry listed in WEB-INF/classpath.idx lives under the single Spring-Boot-Lib directory (WEB-INF/lib/), but an executable WAR legitimately also places the provided / embedded-container dependencies under WEB-INF/lib-provided/ and records them in the classpath index. The first lib-provided entry encountered aborts the command.
Environment
- Spring Boot: 4.1.0
- Packaging: WAR (executable,
WarLauncher) - Java (runtime): 25
- Build: Maven WAR Plugin 3.5.1
Steps to reproduce
A minimal project generated from start.spring.io reproduces the problem.
The key factors are WAR packaging plus the web dependency, which places the embedded Tomcat and spring-boot-web-server artifacts in WEB-INF/lib-provided/.
-
Generate a project (Maven, Java, WAR packaging, Java 25, Spring Boot 4.1.0,
webdependency): -
Build the WAR:
./mvnw package -
Run the
toolsjarmodeextractcommand:java -Djarmode=tools -jar target/demo-0.0.1-SNAPSHOT.war extract
The command fails with the stack trace shown below.
Actual behavior
java.lang.IllegalStateException: java.lang.IllegalStateException: Invalid library location WEB-INF/lib-provided/spring-boot-web-server-4.1.0.jar
at org.springframework.boot.jarmode.tools.ToolsJarMode.run(ToolsJarMode.java:58)
at org.springframework.boot.loader.launch.JarModeRunner.runJarMode(JarModeRunner.java:64)
at org.springframework.boot.loader.launch.JarModeRunner.main(JarModeRunner.java:44)
...
Caused by: java.lang.IllegalStateException: Invalid library location WEB-INF/lib-provided/spring-boot-web-server-4.1.0.jar
at org.springframework.util.Assert.state(Assert.java:102)
at org.springframework.boot.jarmode.tools.IndexedJarStructure.toStructureDependency(IndexedJarStructure.java:133)
at org.springframework.boot.jarmode.tools.IndexedJarStructure.resolve(IndexedJarStructure.java:102)
at org.springframework.boot.jarmode.tools.JarStructure.resolve(JarStructure.java:40)
at org.springframework.boot.jarmode.tools.ExtractCommand.lambda$extractLibraries$0(ExtractCommand.java:162)
...
Expected behavior
extract completes and lays out the archive contents, treating WEB-INF/lib-provided/ entries as libraries (or otherwise handling them) instead of asserting on the Spring-Boot-Lib prefix.
Analysis
The WAR is internally consistent. Manifest, WEB-INF/layers.idx, and WEB-INF/classpath.idx all agree that WEB-INF/lib-provided/ exists and is on the runtime classpath. Relevant manifest attributes:
Spring-Boot-Version: 4.1.0
Spring-Boot-Lib: WEB-INF/lib/
Spring-Boot-Classpath-Index: WEB-INF/classpath.idx
Spring-Boot-Layers-Index: WEB-INF/layers.idx
Main-Class: org.springframework.boot.loader.launch.WarLauncher
During extraction, IndexedJarStructure.resolve(String) classifies every archive entry.
Any entry present in classpathEntries (loaded verbatim from classpath.idx) is treated as a library and passed to toStructureDependency, which asserts on the Spring-Boot-Lib prefix:
private String toStructureDependency(String location) {
Assert.state(location.startsWith(this.libLocation), // libLocation = "WEB-INF/lib/"
() -> "Invalid library location " + location);
return location.substring(this.libLocation.length());
}Our context
We are transitioning from traditional WAR deployments to running Spring Boot applications with the embedded Tomcat. During this transition we need to keep producing WAR files, while still using the tools jarmode to build layered container images. Hence, we would welcome a fix that allows tools extract to work with executable WARs as well.
Activity
[-]jarmode=tools extract fails on executable WAR with scope provided dependencies[/-][+]Add extract support for executable WAR files[/+][-]Add extract support for executable WAR files[/-][+]Add extract support for executable war files[/+]mhalbritter commentedon Aug 12, 2026
Hey,
thanks for the report. The
extractcommand only works with jar files at the moment. This issue tracks the work on adding it for the war files, too.exijn commentedon Aug 26, 2026
Hi, I'd be interested in working on this issue.
I plan to first add a focused regression test that builds an executable WAR with entries in both
WEB-INF/lib/andWEB-INF/lib-provided/, then runs the tools jarmodeextractcommand and verifies the extracted layout.I’ll review how
IndexedJarStructurecurrently maps classpath entries and look for the smallest extension that supports WAR library locations without changing the existing executable JAR behavior.Would this scope and direction be suitable for a contribution?
mhalbritter commentedon Aug 26, 2026
Hello @hej090224 thanks for the offer, but we already have a PR for this: #51372
mhalbritter commentedon Aug 26, 2026
Superseded by #51372.
Support provided-scope libraries when extracting an executable war