quarkusio/quarkus · error · IllegalArgumentException

Interface ${interface} must contain a single implementation

Error message

Interface ${interface} must contain a single implementation whose name ends with 'Impl'. Multiple implementations were found: ${a},${b}

What it means

A custom fragment interface may have multiple implementor classes on the classpath. Quarkus (like Spring Data JPA) picks the implementation whose class name ends with the default suffix 'Impl'; when two or more implementors end with 'Impl' the choice is ambiguous and augmentation fails.

Source

Thrown at extensions/spring-data-jpa/deployment/src/main/java/io/quarkus/spring/data/deployment/generate/FragmentMethodsUtil.java:26

final class FragmentMethodsUtil {

    private FragmentMethodsUtil() {
    }

    /**
     * Returns the simple expected implementation of a Fragment interface or throws an
     * exception indicating the problem
     */
    static DotName getImplementationDotName(DotName customInterfaceToImplement, IndexView index) {
        Collection<ClassInfo> knownImplementors = index.getAllKnownImplementors(customInterfaceToImplement);

        if (knownImplementors.size() > 1) {
            DotName previouslyFound = null;
            for (ClassInfo knownImplementor : knownImplementors) {
                if (knownImplementor.name().toString().endsWith("Impl")) { // the default suffix that Spring Data JPA looks for is 'Impl'
                    if (previouslyFound != null) { // make sure we don't have multiple implementations suffixed with 'Impl'
                        throw new IllegalArgumentException(
                                "Interface " + customInterfaceToImplement
                                        + " must contain a single implementation whose name ends with 'Impl'. Multiple implementations were found: "
                                        + previouslyFound + "," + knownImplementor);
                    }
                    previouslyFound = knownImplementor.name();
                }
            }
            return previouslyFound;
        } else if (knownImplementors.size() == 1) {
            return knownImplementors.iterator().next().name();
        } else {
            throw new IllegalArgumentException(
                    "No implementation of interface " + customInterfaceToImplement + " was found");
        }
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Delete or rename one of the duplicate *Impl classes so only a single *Impl implementor remains
  2. Rename non-primary implementors to a suffix other than 'Impl' (Spring Data convention allows suffix configuration, but Quarkus expects a unique 'Impl')
  3. Use the fully qualified bean with @Component/@Repository and ensure only one candidate exists in the index

Example fix

// before: two implementors
public class PersonRepositoryCustomImpl implements PersonRepositoryCustom { ... }
public class PersonRepositoryCustomImpl2 implements PersonRepositoryCustom { ... }
// after: keep one, rename other to non-'Impl' suffix
public class PersonRepositoryCustomImpl implements PersonRepositoryCustom { ... }
public class LegacyPersonRepositoryCustomFallback implements PersonRepositoryCustom { ... }
Defensive patterns

Strategy: validation

Validate before calling

// Check before build: exactly one *Impl implementor per fragment interface
grep -rl "implements PersonRepositoryCustom" src/main/java | grep -c "Impl\.java" # must be <= 1 for Impl-suffixed

Prevention

When it happens

Trigger: Declaring a fragment interface (e.g. PersonRepositoryCustom) with two classes implementing it whose names both end in 'Impl' (e.g. PersonRepoImpl and AnotherPersonRepoImpl), both visible to the index.

Common situations: Copying and renaming an implementation class without deleting the old one; two modules each providing an 'Impl' for the same fragment interface; refactoring leftovers.

Related errors


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