{"record":{"id":"a4a75ed3e4f8657e","repo":"hibernate/hibernate-orm","slug":"multiple-schemamanagementtool-service-registration","errorCode":null,"errorMessage":"Multiple SchemaManagementTool service registrations found via ServiceLoader; specify one explicitly via 'hibernate.schema_management_tool'","messagePattern":"Multiple SchemaManagementTool service registrations found via ServiceLoader; specify one explicitly via 'hibernate\\.schema_management_tool'","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaManagementToolInitiator.java","lineNumber":47,"sourceCode":"\t\t\t\t.<SchemaManagementTool>resolveDefaultableStrategy( SchemaManagementTool.class,\n\t\t\t\t\t\tconfigurationValues.get( SCHEMA_MANAGEMENT_TOOL ),\n\t\t\t\t\t\t() -> {\n\t\t\t\t\t\t\tfinal var discovered = discover( registry.requireService( ClassLoaderService.class ) );\n\t\t\t\t\t\t\tif ( discovered != null ) {\n\t\t\t\t\t\t\t\treturn discovered;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn registry.requireService( JdbcServices.class ).getDialect()\n\t\t\t\t\t\t\t\t\t.getFallbackSchemaManagementTool( configurationValues, registry );\n\t\t\t\t\t\t} );\n\t}\n\n\tprivate static SchemaManagementTool discover(ClassLoaderService classLoaderService) {\n\t\tfinal var discovered = classLoaderService.loadJavaServices( SchemaManagementTool.class );\n\t\tfinal var iterator = discovered.iterator();\n\t\tif ( iterator.hasNext() ) {\n\t\t\tfinal var selected = iterator.next();\n\t\t\tif ( iterator.hasNext() ) {\n\t\t\t\tthrow new HibernateException(\n\t\t\t\t\t\t\"Multiple SchemaManagementTool service registrations found via ServiceLoader; \"\n\t\t\t\t\t\t+ \"specify one explicitly via '\" + SCHEMA_MANAGEMENT_TOOL + \"'\" );\n\t\t\t}\n\t\t\treturn selected;\n\t\t}\n\t\telse {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Class<SchemaManagementTool> getServiceInitiated() {\n\t\treturn SchemaManagementTool.class;\n\t}\n}\n","sourceCodeStart":29,"sourceCodeEnd":64,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaManagementToolInitiator.java#L29-L64","documentation":"At bootstrap Hibernate discovers the SchemaManagementTool via java.util.ServiceLoader (META-INF/services entries). If more than one implementation is discoverable, picking one would be arbitrary, so SchemaManagementToolInitiator.discover throws and tells you to pin the choice via the hibernate.schema_management_tool setting. Two jars on the classpath each registering the service is the typical cause.","triggerScenarios":"Two or more classpath entries provide META-INF/services/org.hibernate.tool.schema.spi.SchemaManagementTool: hibernate-core present twice in different versions (dependency mediation), a fat/shaded jar that merged service files from two Hibernate artifacts, or an in-house/custom SchemaManagementTool packaged alongside the default one. Thrown while the SessionFactory/EntityManagerFactory is being built.","commonSituations":"Maven/Gradle conflicts pulling two hibernate-core versions (starter BOM plus explicit version); shaded assemblies duplicating META-INF/services lines; adding a custom schema management tool without excluding/consolidating the default registration; upgrading Hibernate where the artifact coordinates changed and both old and new jars remain.","solutions":["Run the dependency tree (mvn dependency:tree, gradle dependencies) and exclude the duplicate hibernate-core (or the duplicate provider jar) so exactly one registration remains on the classpath.","If both tools must coexist, set hibernate.schema_management_tool to the fully-qualified class name of the implementation you want.","In fat jars, inspect the merged META-INF/services/org.hibernate.tool.schema.spi.SchemaManagementTool file for duplicated lines and fix the shading/assembly configuration."],"exampleFix":"// before: two hibernate-core versions on the classpath\nimplementation(\"org.hibernate.orm:hibernate-core:6.2.Final\")\nimplementation(\"some-lib:some-lib:1.0\") // transitively pulls hibernate-core 6.4\n\n// after: align to one version\nimplementation(platform(\"org.hibernate.orm:hibernate-core-bom:6.4.Final\"))\nimplementation(\"org.hibernate.orm:hibernate-core\")\nimplementation(\"some-lib:some-lib:1.0\") { exclude(group = \"org.hibernate.orm\") }","handlingStrategy":"validation","validationCode":"List<SchemaManagementTool> found = new ArrayList<>();\nfor (SchemaManagementTool t : ServiceLoader.load(SchemaManagementTool.class, getClass().getClassLoader())) {\n    found.add(t);\n}\nif (found.size() > 1) {\n    throw new IllegalStateException(\"Ambiguous SchemaManagementTool providers on classpath: \" + found);\n}","typeGuard":null,"tryCatchPattern":"try {\n    emf = Persistence.createEntityManagerFactory(\"pu\");\n} catch (PersistenceException e) {\n    if (e.getCause() instanceof HibernateException h\n            && h.getMessage() != null && h.getMessage().contains(\"Multiple SchemaManagementTool\")) {\n        // dedupe the classpath or set hibernate.schema_management_tool explicitly, then retry bootstrap\n    } else { throw e; }\n}","preventionTips":["Lock Hibernate to a single version with a BOM/dependencyManagement block.","Run duplicate-dependency checks in CI (maven-enforcer, Gradle failOnVersionConflict).","When shipping a custom SchemaManagementTool, exclude or consolidate service registrations explicitly."],"tags":["hibernate","classpath","serviceloader","dependency-conflict","bootstrap"],"backgroundTag":"duplicate-service-registration","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}