quarkusio/quarkus · error · AppModelResolverException

Failed to normalize the dependency graph

Error message

Failed to normalize the dependency graph

What it means

After injecting deployment dependencies, normalize() runs the Maven Resolver's graph transformers (ConflictMarker, ConflictIdSorter, then the session's DependencyGraphTransformer) to produce a conflict-resolved graph. Any RepositoryException raised by these transformers (inconsistent conflict ids, cyclic graph issues, transformer-internal problems) is wrapped in this AppModelResolverException.

Source

Thrown at independent-projects/bootstrap/maven-resolver/src/main/java/io/quarkus/bootstrap/resolver/maven/ApplicationDependencyTreeResolver.java:383

            if (dep == null || dep.isFlagSet(DependencyFlags.VISITED)) {
                continue;
            }
            dep.setFlags(DependencyFlags.VISITED);
            dep.clearFlag(DependencyFlags.RELOADABLE);
            clearReloadableFlag(dep);
        }
    }

    private DependencyNode normalize(RepositorySystemSession session, DependencyNode root) throws AppModelResolverException {
        final DependencyGraphTransformationContext context = new SimpleDependencyGraphTransformationContext(session);
        try {
            // add conflict IDs to the added deployments
            root = new ConflictMarker().transformGraph(root, context);
            // resolves version conflicts
            root = new ConflictIdSorter().transformGraph(root, context);
            root = session.getDependencyGraphTransformer().transformGraph(root, context);
        } catch (RepositoryException e) {
            throw new AppModelResolverException("Failed to normalize the dependency graph", e);
        }
        return root;
    }

    private DependencyNode resolveRuntimeDeps(CollectRequest request) throws AppModelResolverException {
        var session = resolver.getSession();
        if (!CONVERGED_TREE_ONLY && collectReloadableModules) {
            final DefaultRepositorySystemSession mutableSession;
            mutableSession = new DefaultRepositorySystemSession(resolver.getSession());
            mutableSession.setDependencyGraphTransformer(new DependencyGraphTransformer() {

                @Override
                public DependencyNode transformGraph(DependencyNode node, DependencyGraphTransformationContext context)
                        throws RepositoryException {
                    final Map<DependencyNode, DependencyNode> visited = new IdentityHashMap<>();
                    for (DependencyNode c : node.getChildren()) {
                        walk(c, visited);
                    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Run 'mvn dependency:tree -Dverbose' to detect dependency cycles or mediation oddities among your extensions and break any cycle (refactor extension/module structure).
  2. Remove snapshot/workspace local builds of extensions and test with released platform versions to rule out a corrupted graph.
  3. Upgrade Quarkus to the latest patch version — graph normalization edge cases are fixed frequently.
  4. Capture the cause RepositoryException and the full pom/dependency list and report a Quarkus issue if the graph looks ordinary.

Example fix

// before: module A and extension B depend on each other (cycle)
com.acme:lib-a -> io.quarkus.ext:ext-b-deployment
io.quarkus.ext:ext-b-deployment -> com.acme:lib-a
// after: break the cycle by extracting shared code
com.acme:lib-a -> com.acme:lib-common
io.quarkus.ext:ext-b-deployment -> com.acme:lib-common
Defensive patterns

Strategy: validation

Validate before calling

// detect cycles in your module/extension graph before the build
// mvn dependency:tree -Dverbose; fail if an artifact is its own ancestor
static void assertNoCycles(Map<String, Set<String>> deps) {
    for (String root : deps.keySet()) {
        Set<String> seen = new HashSet<>();
        dfs(root, deps, seen);
    }
}

Try / catch

try {
    quarkusBuild();
} catch (AppModelResolverException e) {
    if (e.getMessage().contains("Failed to normalize the dependency graph")) {
        throw new IllegalStateException("Check dependency cycles / conflicting extensions; cause: " + e.getCause(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: normalize(originalSession, root) is called from resolve() after deployment dependency injection; the injected graph causes a transformer to fail — most often due to malformed conflict id state after manual node injection, dependency cycles, or inconsistent optional/scope metadata produced by earlier resolution steps.

Common situations: Dependency cycles among extensions or between application modules and extensions; workspace-built extension versions producing self-referential graphs; Quarkus bootstrap bugs triggered by unusual graphs (rare, often reported upstream); heavily customized session dependency graph transformers.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/34047f2858e40b95. Report an issue: GitHub.