quarkusio/quarkus · error · IllegalStateException
Multiple instances of %1$s were found for Hibernate Search b
Error message
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
What it means
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.
Source
Thrown at extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/bean/HibernateSearchBeanUtil.java:39
public static <T> Optional<BeanReference<T>> singleExtensionBeanReferenceFor(Optional<String> override, Class<T> beanType,
String persistenceUnitName, String backendName, String indexName) {
return override.map(string -> BeanReference.parse(beanType, string))
.or(() -> singleExtensionBeanReferenceFor(beanType, persistenceUnitName, backendName, indexName));
}
private static <T> Optional<BeanReference<T>> singleExtensionBeanReferenceFor(Class<T> beanType,
String persistenceUnitName, String backendName, String indexName) {
InjectableInstance<T> instance = extensionInstanceFor(beanType, persistenceUnitName, backendName, indexName);
if (instance.isAmbiguous()) {
List<String> ambiguousClassNames = instance.handlesStream().map(h -> h.getBean().getBeanClass().getCanonicalName())
.toList();
if (indexName != null) {
throw new IllegalStateException(String.format(Locale.ROOT,
"Multiple instances of %1$s were found for Hibernate Search index %2$s in persistence unit %3$s."
+ " At most one instance can be assigned to each index. Instances found: %4$s",
beanType.getSimpleName(), indexName, persistenceUnitName, ambiguousClassNames));
} else if (backendName != null) {
throw new IllegalStateException(String.format(Locale.ROOT,
"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",
beanType.getSimpleName(), backendName, persistenceUnitName, ambiguousClassNames));
} else {
throw new IllegalStateException(String.format(Locale.ROOT,
"Multiple instances of %1$s were found for Hibernate Search in persistence unit %2$s."
+ " At most one instance can be assigned to each persistence unit. Instances found: %3$s",
beanType.getSimpleName(), persistenceUnitName, ambiguousClassNames));
}
}
return instance.isResolvable() ? Optional.of(new ArcBeanReference<>(instance.getHandle().getBean())) : Optional.empty();
}
public static <T> Optional<List<BeanReference<T>>> multiExtensionBeanReferencesFor(Optional<List<String>> override,
Class<T> beanType,
String persistenceUnitName, String backendName, String indexName) {
return override.map(strings -> strings.stream()
.map(string -> BeanReference.parse(beanType, string))View on GitHub (pinned to e1c734241f)
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.
Example fix
// before: two backend-wide beans of the same type
@SearchExtension(backend = "elasticsearch")
public class MyConfigA implements ElasticsearchConnectionConfigurer { ... }
@SearchExtension(backend = "elasticsearch")
public class MyConfigB implements ElasticsearchConnectionConfigurer { ... }
// after: single backend bean (B removed or repurposed to an index scope)
@SearchExtension(backend = "elasticsearch")
public class MyConfigA implements ElasticsearchConnectionConfigurer { ... }
@SearchExtension(backend = "elasticsearch", index = "Books")
public class MyConfigB implements ... { ... } Defensive patterns
Strategy: validation
Validate before calling
// Verify no duplicate backend-scoped extension beans of the same type:
long count = Arc.container().instance(MyBackendCustomizer.class)
.handlesStream().count();
if (count > 1) {
throw new IllegalStateException("Expected 1 backend customizer, found " + count);
} Try / catch
try {
startHibernateSearch();
} catch (IllegalStateException e) {
if (e.getMessage() != null && e.getMessage().contains("Hibernate Search backend")) {
LOGGER.error("Keep exactly one bean per backend: " + e.getMessage());
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Multiple instances of %1$s were found for Hibernate Search i
- Multiple instances of %1$s were found for Hibernate Search i
- Multiple instances of %1$s were found for Hibernate Search S
- Multiple instances of %1$s were found for Hibernate Search S
- Multiple instances of %1$s were found for Hibernate Search S
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/7353ec35164244d4.
Report an issue: GitHub.