Maven Booted My Spring App Fine. IntelliJ Didn’t. Here’s the One-Checkbox Fix.

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:

  • mvn spring-boot:run treats the JVM it launches as that “runtime environment,” so it includes provided-scope dependencies on the exec classpath.
  • IntelliJ’s Run Configuration does not include provided-scope dependencies by default — and that’s the correct, intentional behavior for the scope’s contract. It’s not a bug; it’s IntelliJ doing exactly what provided is supposed to mean.

    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.

  • Leave a Reply

    Your email address will not be published. Required fields are marked *