{"record":{"id":"3b16ef691e99b14d","repo":"quarkusio/quarkus","slug":"interface-interface-must-contain-a-single-imple","errorCode":null,"errorMessage":"Interface ${interface} must contain a single implementation whose name ends with 'Impl'. Multiple implementations were found: ${a},${b}","messagePattern":"Interface (.+?) must contain a single implementation whose name ends with 'Impl'\\. Multiple implementations were found: (.+?),(.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/spring-data-jpa/deployment/src/main/java/io/quarkus/spring/data/deployment/generate/FragmentMethodsUtil.java","lineNumber":26,"sourceCode":"\nfinal class FragmentMethodsUtil {\n\n    private FragmentMethodsUtil() {\n    }\n\n    /**\n     * Returns the simple expected implementation of a Fragment interface or throws an\n     * exception indicating the problem\n     */\n    static DotName getImplementationDotName(DotName customInterfaceToImplement, IndexView index) {\n        Collection<ClassInfo> knownImplementors = index.getAllKnownImplementors(customInterfaceToImplement);\n\n        if (knownImplementors.size() > 1) {\n            DotName previouslyFound = null;\n            for (ClassInfo knownImplementor : knownImplementors) {\n                if (knownImplementor.name().toString().endsWith(\"Impl\")) { // the default suffix that Spring Data JPA looks for is 'Impl'\n                    if (previouslyFound != null) { // make sure we don't have multiple implementations suffixed with 'Impl'\n                        throw new IllegalArgumentException(\n                                \"Interface \" + customInterfaceToImplement\n                                        + \" must contain a single implementation whose name ends with 'Impl'. Multiple implementations were found: \"\n                                        + previouslyFound + \",\" + knownImplementor);\n                    }\n                    previouslyFound = knownImplementor.name();\n                }\n            }\n            return previouslyFound;\n        } else if (knownImplementors.size() == 1) {\n            return knownImplementors.iterator().next().name();\n        } else {\n            throw new IllegalArgumentException(\n                    \"No implementation of interface \" + customInterfaceToImplement + \" was found\");\n        }\n    }\n}\n","sourceCodeStart":8,"sourceCodeEnd":43,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/spring-data-jpa/deployment/src/main/java/io/quarkus/spring/data/deployment/generate/FragmentMethodsUtil.java#L8-L43","documentation":"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.","triggerScenarios":"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.","commonSituations":"Copying and renaming an implementation class without deleting the old one; two modules each providing an 'Impl' for the same fragment interface; refactoring leftovers.","solutions":["Delete or rename one of the duplicate *Impl classes so only a single *Impl implementor remains","Rename non-primary implementors to a suffix other than 'Impl' (Spring Data convention allows suffix configuration, but Quarkus expects a unique 'Impl')","Use the fully qualified bean with @Component/@Repository and ensure only one candidate exists in the index"],"exampleFix":"// before: two implementors\npublic class PersonRepositoryCustomImpl implements PersonRepositoryCustom { ... }\npublic class PersonRepositoryCustomImpl2 implements PersonRepositoryCustom { ... }\n// after: keep one, rename other to non-'Impl' suffix\npublic class PersonRepositoryCustomImpl implements PersonRepositoryCustom { ... }\npublic class LegacyPersonRepositoryCustomFallback implements PersonRepositoryCustom { ... }","handlingStrategy":"validation","validationCode":"// Check before build: exactly one *Impl implementor per fragment interface\ngrep -rl \"implements PersonRepositoryCustom\" src/main/java | grep -c \"Impl\\.java\" # must be <= 1 for Impl-suffixed","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never duplicate an Impl class when refactoring — delete the old one","Use a single suffix convention: only the active implementor ends with 'Impl'","Search the codebase for all implementors of a fragment interface before adding a new one"],"tags":["quarkus","spring-data-jpa","ambiguous-implementation","build-time"],"backgroundTag":"ambiguous-bean-implementation","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}