quarkusio/quarkus · error · IllegalStateException

Multiple ${AdditionalPersistenceUnitBuildItem} for persisten

Error message

Multiple ${AdditionalPersistenceUnitBuildItem} for persistence unit '${puName}'

What it means

PersistenceUnitDefinitionSupport aggregates AdditionalPersistenceUnitBuildItem entries during persistence unit definition. Each additional build item supplies extra config (datasource, dialect, properties) keyed by persistence unit name; if two such items target the same PU name, the second detection throws IllegalStateException because the config would be ambiguous.

Source

Thrown at extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/component/PersistenceUnitDefinitionSupport.java:169

        // Note:
        // * We do this after deciding whether there should be a default PU on purpose:
        //   we don't want that decision to be affected by AdditionalPersistenceUnitBuildItem.
        // * We are guaranteed at this point that no application-configured PU conflicts:
        //   see checks that prevent using AdditionalPersistenceUnitBuildItem and Quarkus config for the same PU
        //   in HibernateOrmProcessor.
        Map<String, PersistenceUnitDefinitionBuildItem.AdditionalConfig> additionalConfigs = new HashMap<>();
        for (AdditionalPersistenceUnitBuildItem item : additionalPersistenceUnits) {
            String puName = item.getPersistenceUnitName();
            puNamesBlockingOrReactive.add(puName);
            puNamesWithReasons.computeIfAbsent(puName, k -> new ArrayList<>())
                    .add(item.getReason());
            var previous = additionalConfigs.put(puName,
                    new PersistenceUnitDefinitionBuildItem.AdditionalConfig(
                            item.getDataSourceName(),
                            item.getExplicitDialect(), item.getProperties()));
            if (previous != null) {
                throw new IllegalStateException("Multiple " + AdditionalPersistenceUnitBuildItem.class.getSimpleName()
                        + " for persistence unit '" + puName + "'");
            }
        }

        if (LOG.isDebugEnabled()) {
            LOG.debugf("Defining %s persistence units; reasons:\n%s", paradigm,
                    puNamesWithReasons.entrySet().stream()
                            .map(e -> e.getKey() + ": " + Reason.format(e.getValue()))
                            .collect(Collectors.joining("\n")));
        }
        for (var entry : puNamesWithReasons.entrySet()) {
            String puName = entry.getKey();

            List<Reason> unavailableReasons = lookupBuildItem.getLookup().unavailableReasons(puName, paradigm);
            if (!unavailableReasons.isEmpty()) {
                throw new ConfigurationException(String.format(Locale.ROOT,
                        """
                                Hibernate %s persistence unit '%s' cannot be created for the following reason(s):

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove the duplicate AdditionalPersistenceUnitBuildItem contribution — keep one source of config per persistence unit
  2. Check for conflicting config between standard and reactive Hibernate ORM extensions for the same PU
  3. If you write custom build steps, guard against emitting an item when one already exists for the PU name

Example fix

// before (duplicate contributions for 'pu1' from two extensions)
quarkus.hibernate-orm."pu1".datasource=ds1
quarkus.hibernate-reactive."pu1".datasource=ds2
// after (use only one paradigm per PU)
quarkus.hibernate-orm."pu1".datasource=ds1
Defensive patterns

Strategy: validation

Validate before calling

// Keep one paradigm/config source per persistence unit
Map<String,String> owners = new HashMap<>();
void contribute(String pu, String source) {
    if (owners.putIfAbsent(pu, source) != null)
        throw new IllegalStateException("PU " + pu + " already configured by " + owners.get(pu));
}

Prevention

When it happens

Trigger: Two extensions or configuration sources each produce an AdditionalPersistenceUnitBuildItem for the same persistence unit name while definePersistenceUnits processes them.

Common situations: Having both quarkus.hibernate-orm datasource/dialect config and another ORM paradigm (e.g. reactive) extension contributing config for the same PU; duplicate extension config blocks; user-defined build steps emitting a duplicate item.

Related errors


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