quarkusio/quarkus · error · IllegalStateException

Multiple instances of %1$s were found for Hibernate Search S

Error message

Multiple instances of %1$s were found for Hibernate Search Standalone index %2$s. At most one instance can be assigned to each index. Instances found: %3$s

What it means

HibernateSearchBeanUtil.singleExtensionBeanReferenceFor() resolves the single extension-provided bean assignable to beanType, scoped optionally to a backend and index. If the ArC InjectableInstance is ambiguous (more than one matching bean), it throws IllegalStateException listing the candidate classes. Hibernate Search requires at most one bean per index scope, so multiple user/extension beans for the same role are a configuration error.

Source

Thrown at extensions/hibernate-search-standalone-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/standalone/elasticsearch/runtime/bean/HibernateSearchBeanUtil.java:34

public final class HibernateSearchBeanUtil {

    private HibernateSearchBeanUtil() {
    }

    public static <T> Optional<BeanReference<T>> singleExtensionBeanReferenceFor(Optional<String> override, Class<T> beanType,
            String backendName, String indexName) {
        return override.map(string -> BeanReference.parse(beanType, string))
                .or(() -> singleExtensionBeanReferenceFor(beanType, backendName, indexName));
    }

    private static <T> Optional<BeanReference<T>> singleExtensionBeanReferenceFor(Class<T> beanType,
            String backendName, String indexName) {
        InjectableInstance<T> instance = extensionInstanceFor(beanType, 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 Standalone index %2$s."
                                + " At most one instance can be assigned to each index. Instances found: %3$s",
                        beanType.getSimpleName(), indexName, ambiguousClassNames));
            } else if (backendName != null) {
                throw new IllegalStateException(String.format(Locale.ROOT,
                        "Multiple instances of %1$s were found for Hibernate Search Standalone backend %2$s."
                                + " At most one instance can be assigned to each backend. Instances found: %3$s",
                        beanType.getSimpleName(), backendName, ambiguousClassNames));
            } else {
                throw new IllegalStateException(String.format(Locale.ROOT,
                        "Multiple instances of %1$s were found for Hibernate Search Standalone."
                                + " At most one instance can be assigned. Instances found: %2$s",
                        beanType.getSimpleName(), ambiguousClassNames));
            }
        }
        return instance.isResolvable() ? Optional.of(new ArcBeanReference<>(instance.getHandle().getBean())) : Optional.empty();
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove or de-register one of the duplicate beans so only one matches the given index.
  2. Differentiate the beans' @HibernateSearchExtension qualifiers (distinct index/backend names) so each index resolves exactly one bean.
  3. Use quarkus.hibernate-search-standalone.* config to exclude or override the conflicting bean (e.g. expose the built-in bean for a different backend).
  4. Inspect the 'Instances found' list in the message and delete the stale/duplicate class.

Example fix

// before: two beans target the same index
@HibernateSearchExtension(backend = "elasticsearch", index = "Book")
@ApplicationScoped public class LoaderA implements EntityLoader { ... }
@HibernateSearchExtension(backend = "elasticsearch", index = "Book")
@ApplicationScoped public class LoaderB implements EntityLoader { ... }

// after: qualify differently or delete one
@HibernateSearchExtension(backend = "elasticsearch", index = "Book")
@ApplicationScoped public class LoaderA implements EntityLoader { ... }
Defensive patterns

Strategy: validation

Validate before calling

// Detect ambiguity before Hibernate Search resolution
InjectableInstance<MyType> i = Arc.container().select(MyType.class, qualifier);
if (i.isAmbiguous()) {
    throw new IllegalStateException("Multiple beans for index X: " + i.getHandles());
}

Type guard

public static <T> boolean hasSingleBean(Class<T> type, Annotation... qualifiers) {
    var instance = Arc.container().select(type, qualifiers);
    return instance.isResolvable() && !instance.isAmbiguous();
}

Try / catch

try {
    Optional<BeanReference<T>> ref = HibernateSearchBeanUtil.singleExtensionBeanReferenceFor(beanType, backend, index);
} catch (IllegalStateException e) {
    log.errorf("Duplicate Hibernate Search beans — keep only one per index: %s", e.getMessage(), e);
}

Prevention

When it happens

Trigger: Two or more beans of the requested type carry the same @HibernateSearchExtension(...) qualifier that targets the same index (indexName != null), so instance.isAmbiguous() is true when resolving for that index.

Common situations: Registering two custom implementations (e.g. two entity-loading or two document-mapper beans) both annotated @HibernateSearchExtension with the same index name; upgrading the extension while an old bean is still present; accidentally leaving a duplicate bean after copying a class.

Related errors


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