{"record":{"id":"7353ec35164244d4","repo":"quarkusio/quarkus","slug":"multiple-instances-of-1-s-were-found-for-hibernat-7353ec","errorCode":null,"errorMessage":"Multiple instances of %1$s were found for Hibernate Search backend %2$s in persistence unit %3$s. At most one instance can be assigned to each backend. Instances found: %4$s","messagePattern":"Multiple instances of %1\\$s were found for Hibernate Search backend %2\\$s in persistence unit %3\\$s\\. At most one instance can be assigned to each backend\\. Instances found: %4\\$s","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/bean/HibernateSearchBeanUtil.java","lineNumber":39,"sourceCode":"    public static <T> Optional<BeanReference<T>> singleExtensionBeanReferenceFor(Optional<String> override, Class<T> beanType,\n            String persistenceUnitName, String backendName, String indexName) {\n        return override.map(string -> BeanReference.parse(beanType, string))\n                .or(() -> singleExtensionBeanReferenceFor(beanType, persistenceUnitName, backendName, indexName));\n    }\n\n    private static <T> Optional<BeanReference<T>> singleExtensionBeanReferenceFor(Class<T> beanType,\n            String persistenceUnitName, String backendName, String indexName) {\n        InjectableInstance<T> instance = extensionInstanceFor(beanType, persistenceUnitName, backendName, indexName);\n        if (instance.isAmbiguous()) {\n            List<String> ambiguousClassNames = instance.handlesStream().map(h -> h.getBean().getBeanClass().getCanonicalName())\n                    .toList();\n            if (indexName != null) {\n                throw new IllegalStateException(String.format(Locale.ROOT,\n                        \"Multiple instances of %1$s were found for Hibernate Search index %2$s in persistence unit %3$s.\"\n                                + \" At most one instance can be assigned to each index. Instances found: %4$s\",\n                        beanType.getSimpleName(), indexName, persistenceUnitName, ambiguousClassNames));\n            } else if (backendName != null) {\n                throw new IllegalStateException(String.format(Locale.ROOT,\n                        \"Multiple instances of %1$s were found for Hibernate Search backend %2$s in persistence unit %3$s.\"\n                                + \" At most one instance can be assigned to each backend. Instances found: %4$s\",\n                        beanType.getSimpleName(), backendName, persistenceUnitName, ambiguousClassNames));\n            } else {\n                throw new IllegalStateException(String.format(Locale.ROOT,\n                        \"Multiple instances of %1$s were found for Hibernate Search in persistence unit %2$s.\"\n                                + \" At most one instance can be assigned to each persistence unit. Instances found: %3$s\",\n                        beanType.getSimpleName(), persistenceUnitName, ambiguousClassNames));\n            }\n        }\n        return instance.isResolvable() ? Optional.of(new ArcBeanReference<>(instance.getHandle().getBean())) : Optional.empty();\n    }\n\n    public static <T> Optional<List<BeanReference<T>>> multiExtensionBeanReferencesFor(Optional<List<String>> override,\n            Class<T> beanType,\n            String persistenceUnitName, String backendName, String indexName) {\n        return override.map(strings -> strings.stream()\n                .map(string -> BeanReference.parse(beanType, string))","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/bean/HibernateSearchBeanUtil.java#L21-L57","documentation":"Same resolution failure as the index-level variant, but scoped to an entire Hibernate Search backend: HibernateSearchBeanUtil.singleExtensionBeanReferenceFor found more than one CDI bean of the requested type for the named backend (indexName was null, backendName was non-null) in the given persistence unit. At most one instance may be assigned per backend, so the extension throws IllegalStateException listing all matching bean classes.","triggerScenarios":"singleExtensionBeanReferenceFor invoked with indexName == null and backendName != null; extensionInstanceFor(...) selects beans qualified with @SearchExtension(backend = \"<name>\") (no index qualifier), and the resulting InjectableInstance is ambiguous (isAmbiguous() true).","commonSituations":"Two @SearchExtension(backend = \"elasticsearch\")-annotated beans of the same type (e.g. two DocumentReferenceProviders, two mass indexers customizations, two connection/tenant configurations) without an index qualifier; a user override bean plus the extension's @DefaultBean both active because the override lacks @Alternative/@Priority; duplicate registrations after upgrading Hibernate Search where an old customizer bean remains.","solutions":["Inspect 'Instances found: [A, B]' and remove one of the duplicated backend-scoped beans.","Narrow each bean's scope with an index-level qualifier (@SearchExtension(backend = ..., index = ...)) if both are intentionally index-specific, so backend resolution sees one bean.","Mark your override with @Alternative and @Priority so it replaces the @DefaultBean instead of coexisting with it.","Verify only one @SearchExtension qualifier matches by checking the backend name spelling in the annotations."],"exampleFix":"// before: two backend-wide beans of the same type\n@SearchExtension(backend = \"elasticsearch\")\npublic class MyConfigA implements ElasticsearchConnectionConfigurer { ... }\n@SearchExtension(backend = \"elasticsearch\")\npublic class MyConfigB implements ElasticsearchConnectionConfigurer { ... }\n\n// after: single backend bean (B removed or repurposed to an index scope)\n@SearchExtension(backend = \"elasticsearch\")\npublic class MyConfigA implements ElasticsearchConnectionConfigurer { ... }\n@SearchExtension(backend = \"elasticsearch\", index = \"Books\")\npublic class MyConfigB implements ... { ... }","handlingStrategy":"validation","validationCode":"// Verify no duplicate backend-scoped extension beans of the same type:\nlong count = Arc.container().instance(MyBackendCustomizer.class)\n    .handlesStream().count();\nif (count > 1) {\n    throw new IllegalStateException(\"Expected 1 backend customizer, found \" + count);\n}","typeGuard":null,"tryCatchPattern":"try {\n    startHibernateSearch();\n} catch (IllegalStateException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Hibernate Search backend\")) {\n        LOGGER.error(\"Keep exactly one bean per backend: \" + e.getMessage());\n    }\n    throw e;\n}","preventionTips":["Don't leave old customizer beans after upgrading; remove superseded classes.","Scope beans as narrowly as possible (index qualifier) so backend-level lookups stay unique.","In tests, use profiles to veto production duplicates rather than adding more beans."],"tags":["quarkus","cdi","hibernate-search","elasticsearch","ambiguous-bean"],"backgroundTag":"ambiguous-cdi-bean","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}