{"record":{"id":"11bd8c31431b92c2","repo":"hibernate/hibernate-orm","slug":"unable-to-instantiate-statementobserver","errorCode":null,"errorMessage":"Unable to instantiate StatementObserver - {}","messagePattern":"Unable to instantiate StatementObserver - (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java","lineNumber":605,"sourceCode":"\t}\n\n\t@Nullable\n\tprivate StatementObserver interpretStatementObserver(Map<String, Object> settings) {\n\t\tvar setting = settings.get( JdbcSettings.STATEMENT_OBSERVER );\n\t\tif ( setting == null ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( setting instanceof StatementObserver observer ) {\n\t\t\treturn observer;\n\t\t}\n\n\t\tif ( setting instanceof Class<?> impl ) {\n\t\t\ttry {\n\t\t\t\treturn (StatementObserver) impl.getConstructor().newInstance();\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tthrow new RuntimeException( \"Unable to instantiate StatementObserver - \" + impl.getName(), e );\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tvar namedImpl = Class.forName( setting.toString() );\n\t\t\treturn (StatementObserver) namedImpl.getConstructor().newInstance();\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new RuntimeException( \"Unable to instantiate StatementObserver - \" + setting, e );\n\t\t}\n\t}\n\n\t@Nullable\n\tprivate TimeZone getJdbcTimeZone(Object jdbcTimeZoneValue) {\n\t\tif ( jdbcTimeZoneValue instanceof TimeZone timeZone ) {\n\t\t\treturn timeZone;\n\t\t}\n\t\telse if ( jdbcTimeZoneValue instanceof ZoneId zoneId ) {","sourceCodeStart":587,"sourceCodeEnd":623,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java#L587-L623","documentation":"SessionFactoryOptionsBuilder reads the hibernate.statement_observer setting, which accepts a StatementObserver instance, a Class object, or a class-name String. When a Class is supplied, Hibernate reflectively calls its public no-arg constructor (impl.getConstructor().newInstance()); any failure is rethrown as this RuntimeException naming the class, with the original cause attached.","triggerScenarios":"Setting hibernate.statement_observer to a Class that is abstract, lacks a public no-arg constructor, or whose constructor throws; the failure happens during SessionFactoryOptions building, i.e. at SessionFactory bootstrap.","commonSituations":"Observer written with only a constructor taking arguments (e.g. a metrics registry); constructor not public; constructor body throws because it expects container injection; observer class uses optional dependencies absent in the test classpath.","solutions":["Add a public no-argument constructor to the observer class","Read the nested cause: InvocationTargetException means the constructor body threw — fix that exception","Prefer passing a fully-built StatementObserver instance via SessionFactoryBuilder#applyStatementObserver (or the setting) instead of a Class, so construction is under your control","Keep construction side-effect free and resolve collaborators lazily"],"exampleFix":"// before:\nprops.put(\"hibernate.statement_observer\", MetricsObserver.class);\n// MetricsObserver only has MetricsObserver(MeterRegistry registry)\n\n// after: pass a ready instance\nMeterRegistry registry = Metrics.registries();\nprops.put(\"hibernate.statement_observer\", new MetricsObserver(registry));","handlingStrategy":"validation","validationCode":"// if you register a Class, verify its constructor shape first\nstatic boolean hasPublicNoArgCtor(Class<?> c) {\n    try { return Modifier.isPublic(c.getConstructor().getModifiers()); }\n    catch (NoSuchMethodException e) { return false; }\n}\n\nif (!hasPublicNoArgCtor(MetricsObserver.class)) throw new IllegalStateException(\"observer needs public no-arg ctor\");\nprops.put(\"hibernate.statement_observer\", MetricsObserver.class);","typeGuard":"static boolean isStatementObserverSettingValid(Object value) {\n    if (value instanceof StatementObserver || value == null) return true;\n    if (value instanceof Class<?> c) return StatementObserver.class.isAssignableFrom(c) && hasPublicNoArgCtor(c);\n    return false; // strings handled by Class.forName path\n}","tryCatchPattern":"try {\n    sessionFactory = new Configuration().addProperties(props).buildSessionFactory();\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Unable to instantiate StatementObserver\")) {\n        // fix config; e.getCause() tells why construction failed\n    }\n    throw e;\n}","preventionTips":["Pass a pre-built StatementObserver instance instead of a Class whenever possible","Keep observer constructors side-effect free; resolve collaborators lazily","Cover the property in a bootstrap test so it fails before deployment"],"tags":["hibernate","statement-observer","reflection","configuration","bootstrap"],"backgroundTag":"reflection-instantiation-failed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}