Maven Assembly "duplicate" / Wrong Manifest - Fix Fat-Jar Build in CI
The maven-assembly-plugin built a jar-with-dependencies and either packed duplicate entries from overlapping jars or produced a jar that will not launch - no main manifest attribute - because no Main-Class was set. Assembly, unlike shade, does not merge service files, so collisions are common.
What this error means
The assembly builds with duplicate warnings for repeated paths, and running the fat jar fails with no main manifest attribute, in app-jar-with-dependencies.jar because the manifest has no entry point.
[INFO] Building jar: target/app-1.0.0-jar-with-dependencies.jar
# at runtime:
$ java -jar target/app-1.0.0-jar-with-dependencies.jar
no main manifest attribute, in target/app-1.0.0-jar-with-dependencies.jarCommon causes
No Main-Class configured in the assembly manifest
The jar-with-dependencies descriptor does not set a <mainClass>, so the manifest has no Main-Class and java -jar cannot find an entry point.
Overlapping entries from multiple jars
Assembly concatenates dependency contents without merging. Two jars with the same resource path produce duplicate entries; service files from different jars overwrite each other.
How to fix it
Set the Main-Class in the assembly archive config
Add the manifest entry so the fat jar is runnable.
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.example.App</mainClass>
</manifest>
</archive>
</configuration>Prefer shade when you need merged service files
If your dependencies use SPI/service files, the shade plugin (with ServicesResourceTransformer) merges them; assembly does not.
# build then verify the entry point:
mvn -B package
unzip -p target/app-1.0.0-jar-with-dependencies.jar META-INF/MANIFEST.MF | grep Main-ClassHow to prevent it
- Always set
<mainClass>when building a runnable jar-with-dependencies. - Use the shade plugin (with transformers) when dependencies rely on service files.
- Verify
Main-Classin the built manifest as a CI smoke check.