quarkusio/quarkus · error · IllegalStateException

Multiple instances of %1$s were found for persistence unit %

Error message

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

What it means

PersistenceUnitUtil enforces that at most one bean of a given extension type (e.g. a single Persistencer/KnownPersistenceUnit holder or interceptor) is assigned to a given persistence unit. When the CDI InjectableInstance for (beanType, PU name, qualifiers) resolves ambiguously — multiple beans match — this IllegalStateException is thrown listing all found bean classes.

Source

Thrown at extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/PersistenceUnitUtil.java:48

    public static Annotation qualifier(String persistenceUnitName) {
        if (isDefaultPersistenceUnit(persistenceUnitName)) {
            return Default.Literal.INSTANCE;
        } else {
            return new PersistenceUnit.PersistenceUnitLiteral(persistenceUnitName);
        }
    }

    public static <T> InjectableInstance<T> singleExtensionInstanceForPersistenceUnit(
            Class<T> beanType,
            String persistenceUnitName,
            Annotation... additionalQualifiers) {
        InjectableInstance<T> instance = extensionInstancesForPersistenceUnit(beanType, persistenceUnitName,
                additionalQualifiers);
        if (instance.isAmbiguous()) {
            List<String> ambiguousClassNames = instance.handlesStream().map(h -> h.getBean().getBeanClass().getCanonicalName())
                    .toList();
            throw new IllegalStateException(String.format(Locale.ROOT,
                    "Multiple instances of %1$s were found for 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;
    }

    public static <T> InjectableInstance<T> extensionInstancesForPersistenceUnit(
            Class<T> beanType,
            String persistenceUnitName,
            Annotation... additionalQualifiers) {
        if (additionalQualifiers.length == 0) {
            return Arc.container().select(beanType, new PersistenceUnitExtension.Literal(persistenceUnitName));
        } else {
            Annotation[] qualifiers = Arrays.copyOf(additionalQualifiers, additionalQualifiers.length + 1);
            qualifiers[additionalQualifiers.length] = new PersistenceUnitExtension.Literal(persistenceUnitName);
            return Arc.container().select(beanType, qualifiers);
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Keep exactly one bean of that type per persistence unit, or annotate each with a distinct @PersistenceUnitExtension qualifier (e.g. @ReactiveTenantConnectionResolver variants).
  2. Use @Alternative/@Priority to disable one of the duplicate beans.
  3. Inspect the 'Instances found' list in the message and remove or qualify the redundant class.
  4. For multi-PU apps, narrow each bean with @PersistenceUnitExtension(persistenceUnitName = "...").

Example fix

// before (two beans for same PU)
@PersistenceUnitExtension class MyProviderA implements ... {}
@PersistenceUnitExtension class MyProviderB implements ... {}
// after
@PersistenceUnitExtension(persistenceUnitName = "pu1") class MyProviderA implements ... {}
@PersistenceUnitExtension(persistenceUnitName = "pu2") class MyProviderB implements ... {}
Defensive patterns

Strategy: validation

Validate before calling

// Validate unambiguity at startup instead of at first use
InjectableInstance<T> i = instance.select(beanType, qualifiers);
if (i.isAmbiguous()) { throw new IllegalArgumentException("Multiple " + beanType + " beans for PU"); }

Prevention

When it happens

Trigger: Declaring two CDI beans of the same extension interface/class (e.g. two custom Persisters, two TenantConnectionProviders) both applicable to the same PU; beans with qualifiers that don't exclude each other; accidentally annotating a second class with the same @PersistenceUnitExtension qualifier/scope.

Common situations: Multi-tenancy setups where a developer adds a second extension bean per tenant but forgets @PersistenceUnitExtensionqualifiers; copy-pasting a CDI bean class; @Alternative not declared so both beans are enabled.

Related errors


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