The setup: A Spring Boot service that booted perfectly with mvn spring-boot:run, but crashed immediately when launched from IntelliJ’s Run/Debug configuration — same code, same machine, same dependencies.
The error: Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: ... Caused by: java.lang.IllegalArgumentException: Could not find class [com.azure.cosmos.models.CompositePathSortOrder] Caused by: java.lang.ClassNotFoundException: com.azure.cosmos.models.CompositePathSortOrder
Spring’s classpath scanner hit an annotation referencing a class that, according to the JVM, didn’t exist.
First instinct — wrong: This looked like a version conflict. My local Maven repo had several versions of the library in question cached side by side, so a mismatch seemed like the obvious suspect. It wasn’t. Every version was internally consistent; the class was exactly where it should be.
Finding the real cause: Instead of guessing further, I asked Maven directly where this dependency actually comes from:
mvn dependency:tree -Dincludes=
The output told the whole story in one line:
my-app
\- some-transitive-library:jar:x.y.z:provided
\- the-missing-library:jar:x.y.z:provided
provided scope. That’s Maven’s way of saying: “this dependency is needed to compile against, but something else — a container, an app server, the deployment environment — supplies it at runtime. Don’t bundle it.”
Why the two tools disagreed:
Same POM, same dependency graph, two different — both legitimate — interpretations of one Maven scope.
The fix, once the cause was clear, took ten seconds: open the Run/Debug Configuration, click Modify options, and enable:
"Add dependencies with 'provided' scope to classpath"
No POM edits. No version pinning. No cache invalidation. Rerun — boots clean.
The lesson, generalized: When a Maven-launched app and an IDE-launched app disagree on a missing class that genuinely exists in your dependency tree, don’t reach for version conflicts first. Check scope. mvn dependency:tree -Dincludes= will show you exactly which dependency brought a class in and under what scope — that single fact usually explains the whole discrepancy, and the fix is often a checkbox, not a rebuild.