{"record":{"id":"b7837f7b5c018e97","repo":"hibernate/hibernate-orm","slug":"persistence-unit-can-only-have-a-single-class","errorCode":null,"errorMessage":"Persistence unit [{}] can only have a single class transformer.","messagePattern":"Persistence unit \\[(.+?)\\] can only have a single class transformer\\.","errorType":"exception","errorClass":"PersistenceException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/PersistenceUnitInfoDescriptor.java","lineNumber":143,"sourceCode":"\t@Override\n\tpublic List<String> getMappingFileNames() {\n\t\treturn persistenceUnitInfo.getMappingFileNames();\n\t}\n\n\t@Override\n\tpublic List<URL> getJarFileUrls() {\n\t\treturn persistenceUnitInfo.getJarFileUrls();\n\t}\n\n\t@Override\n\tpublic boolean isClassTransformerRegistrationDisabled() {\n\t\treturn disableClassTransformerRegistration;\n\t}\n\n\t@Override\n\tpublic ClassTransformer pushClassTransformer(EnhancementContext enhancementContext) {\n\t\tif ( this.classTransformer != null ) {\n\t\t\tthrow new PersistenceException(\n\t\t\t\t\t\"Persistence unit [\"\n\t\t\t\t\t+ persistenceUnitInfo.getPersistenceUnitName()\n\t\t\t\t\t+ \"] can only have a single class transformer.\"\n\t\t\t);\n\t\t}\n\n\t\tfinal TransformerKey transformerKey = TransformerKey.from( persistenceUnitInfo );\n\t\tif ( !TransformerTracker.canSupplyTransformer( transformerKey ) ) {\n\t\t\t// transformer was already registered from `jakarta.persistence.spi.PersistenceProvider#getClassTransformer`\n\t\t\t// just skip\n\t\t\tif ( JPA_LOGGER.isTraceEnabled() ) {\n\t\t\t\tJPA_LOGGER.duplicatedRequestForClassTransformer( transformerKey.puName(), transformerKey.loaderName() );\n\t\t\t}\n\t\t\t// EARLY EXIT!!!\n\t\t\treturn null;\n\t\t}\n\n\t\t// During testing, we will return a null temp class loader","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/PersistenceUnitInfoDescriptor.java#L125-L161","documentation":"Thrown by PersistenceUnitInfoDescriptor.pushClassTransformer() as a PersistenceException when a second class transformer registration is attempted for the same persistence unit. Hibernate allows exactly one ClassTransformer per persistence unit because bytecode enhancement is applied once, up front; any subsequent pushClassTransformer call is treated as a configuration error rather than being silently ignored.","triggerScenarios":"Calling pushClassTransformer() twice on the same PersistenceUnitInfoDescriptor - typically one call from Hibernate's enhancement support and another from user code or a second integrator/bootstrapper touching the same persistence unit during startup.","commonSituations":"Two frameworks or integrators both trying to register a ClassTransformer on the same PU (e.g. a custom agent plus container-driven enhancement); re-running bootstrap logic against the same PersistenceUnitInfo without a fresh descriptor; duplicated integration code after refactoring startup.","solutions":["Register the transformer only once per persistence unit; remove or guard the duplicate pushClassTransformer call.","Check isClassTransformerRegistrationDisabled() before pushing and skip when a transformer is already in place.","Create a fresh PersistenceUnitInfoDescriptor for a second bootstrap instead of reusing the same instance.","If a container already registered the transformer, rely on that registration instead of adding your own."],"exampleFix":"// before\ntransformer1 = descriptor.pushClassTransformer(ctx);\ntransformer2 = descriptor.pushClassTransformer(ctx); // throws\n\n// after\ntransformer1 = descriptor.pushClassTransformer(ctx);\nif (transformer1 == null) { transformer1 = descriptor.pushClassTransformer(ctx); } // only when none yet","handlingStrategy":"validation","validationCode":"// push at most one transformer per persistence unit\nif (!persistenceUnitInfo.isClassTransformerRegistrationDisabled() && transformerHolder.get() == null) {\n    transformerHolder.set(descriptor.pushClassTransformer(enhancementContext));\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Centralize transformer registration in one startup component and track the registered instance.","Reuse the transformer returned by the first push instead of pushing again."],"tags":["hibernate","jpa","bytecode-enhancement","class-transformer","persistence-unit"],"backgroundTag":"duplicate-component-registration","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}