{"record":{"id":"8827e448111103e9","repo":"hibernate/hibernate-orm","slug":"could-not-instantiate-named-strategy-class","errorCode":null,"errorMessage":"Could not instantiate named strategy class [{}]","messagePattern":"Could not instantiate named strategy class \\[(.+?)\\]","errorType":"exception","errorClass":"StrategySelectionException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java","lineNumber":728,"sourceCode":"\t\t\t\t\t\t}\n\t\t\t\t\t\telse if ( hasStrategyConstructorSignature( parameterTypes ) ) {\n\t\t\t\t\t\t\tentityBasedConstructor = (Constructor<SqmMultiTableMutationStrategy>) declaredConstructor;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( entityBasedConstructor == null ) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif ( dialectConstructor != null ) {\n\t\t\t\t\t\t\t\treturn dialectConstructor.newInstance(\n\t\t\t\t\t\t\t\t\t\tserviceRegistry.requireService( JdbcServices.class ).getDialect()\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if ( emptyConstructor != null ) {\n\t\t\t\t\t\t\t\treturn emptyConstructor.newInstance();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (Exception e) {\n\t\t\t\t\t\t\tthrow new StrategySelectionException(\n\t\t\t\t\t\t\t\t\t\"Could not instantiate named strategy class [\" + strategyClass.getName() + \"]\",\n\t\t\t\t\t\t\t\t\te\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow new IllegalArgumentException( \"Cannot instantiate the class [\" + strategyClass.getName()\n\t\t\t\t\t\t\t\t+ \"] because it does not have a constructor that accepts a dialect or an empty constructor\" );\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t);\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\t@Nullable\n\tprivate Constructor<SqmMultiTableMutationStrategy> resolveSqmMutationStrategyConstructor(\n\t\t\tString strategyName,","sourceCodeStart":710,"sourceCodeEnd":746,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java#L710-L746","documentation":"When hibernate.query.mutation_strategy names a custom SqmMultiTableMutationStrategy class, SessionFactoryOptionsBuilder tries to instantiate it via its Dialect-accepting constructor or its no-arg constructor. If the chosen constructor exists but invocation fails (constructor body throws, class is abstract, or access is denied), a StrategySelectionException wrapping the cause is thrown during SessionFactory bootstrap.","triggerScenarios":"Setting hibernate.query.mutation_strategy=com.acme.MyStrategy where MyStrategy has a Dialect or no-arg constructor whose body throws (commonly NPE from missing services), or the class/constructor is not accessible to reflection.","commonSituations":"Custom strategy assumes a connection or configuration source that is null at bootstrap time; constructor performs dialect feature checks that fail on unexpected dialects; strategy class made package-private or constructor made private after refactoring; upgrading Hibernate changes constructor invocation order.","solutions":["Read the nested cause of the StrategySelectionException — InvocationTargetException.getCause() points at the real failure inside your constructor","Make the strategy class and its Dialect/no-arg constructor public","Move heavy initialization out of the constructor; defer to first use when the runtime context is available","If the strategy needs per-entity context, provide a public (EntityMappingType, RuntimeModelCreationContext) constructor instead"],"exampleFix":"// before:\npublic MyMutationStrategy(Dialect dialect) {\n    this.schema = requireGlobalConfig().getSchema(); // throws NPE at bootstrap\n}\n\n// after:\npublic MyMutationStrategy(Dialect dialect) {\n    this.dialect = dialect; // defer schema resolution to first use\n}\npublic String schema() { return GlobalConfigHolder.schema(); }","handlingStrategy":"try-catch","validationCode":"// verify the strategy's constructor shape before boot\nstatic boolean hasSupportedStrategyCtor(Class<?> c) {\n    return Arrays.stream(c.getDeclaredConstructors()).anyMatch(ctor -> {\n        Class<?>[] p = ctor.getParameterTypes();\n        return java.lang.reflect.Modifier.isPublic(ctor.getModifiers())\n            && (p.length == 0 || (p.length == 1 && Dialect.class.isAssignableFrom(p[0]))\n                || (p.length == 2 && p[0] == EntityMappingType.class\n                    && p[1] == RuntimeModelCreationContext.class));\n    });\n}","typeGuard":null,"tryCatchPattern":"try {\n    sessionFactory = metadata.buildSessionFactory();\n} catch (StrategySelectionException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"hibernate.query.mutation_strategy class\")) {\n        Throwable root = e.getCause();\n        while (root.getCause() != null) root = root.getCause();\n        log.error(\"Custom mutation strategy constructor failed: {}\", root, e);\n    }\n    throw e;\n}","preventionTips":["Keep strategy constructors trivial — no service lookups, no dialect feature calls","Write a dedicated bootstrap test that builds the factory with the custom strategy on all target dialects","Log the registered strategy class at startup so failures are traceable to config"],"tags":["hibernate","strategy","reflection","mutation-strategy","bootstrap"],"backgroundTag":"reflection-instantiation-failed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}