SLF4J "Class path contains multiple SLF4J bindings" - Fix in CI
SLF4J found more than one logging binding (provider) on the classpath. It binds to whichever it loads first, which is non-deterministic across runners, so logging behavior - and sometimes a strict build - becomes unreliable.
What this error means
The log shows SLF4J: Class path contains multiple SLF4J bindings. listing two or more StaticLoggerBinder/provider jars (e.g. logback plus log4j-slf4j). Some builds promote this warning to an error, or logging silently goes to the wrong backend.
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [.../logback-classic-1.5.6.jar!/org/slf4j/impl/...]
SLF4J: Found binding in [.../slf4j-log4j12-1.7.36.jar!/org/slf4j/impl/...]
SLF4J: Actual binding is of type [ch.qos.logback.classic.util...]Common causes
Two backends pulled transitively
One dependency brings logback while another brings log4j (or slf4j-simple), so two bindings coexist.
A library bundles its own logging
A test or runtime library ships a binding you did not intend, duplicating the app backend.
Both slf4j-log4j and log4j-slf4j present
Mixing the legacy and modern bridges puts two providers on the path.
How to fix it
Find the duplicate binding
Locate which dependency drags in the second backend.
./gradlew dependencyInsight --configuration runtimeClasspath \
--dependency org.slf4j:slf4j-log4j12Exclude the unwanted backend
Keep one binding and exclude the rest.
configurations.all {
exclude group: 'org.slf4j', module: 'slf4j-log4j12'
exclude group: 'log4j', module: 'log4j'
}Exclude transitively (Maven)
Drop the duplicate provider from the dependency that brings it.
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>How to prevent it
- Keep exactly one SLF4J binding on the classpath.
- Use the right bridge (e.g.
log4j-over-slf4j) instead of a second real backend. - Audit logging dependencies with
dependencyInsight/dependency:tree.