hibernate/hibernate-orm · error · RuntimeException

Unable to instantiate StatementObserver - {}

Error message

Unable to instantiate StatementObserver - {}

What it means

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.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java:605

	}

	@Nullable
	private StatementObserver interpretStatementObserver(Map<String, Object> settings) {
		var setting = settings.get( JdbcSettings.STATEMENT_OBSERVER );
		if ( setting == null ) {
			return null;
		}

		if ( setting instanceof StatementObserver observer ) {
			return observer;
		}

		if ( setting instanceof Class<?> impl ) {
			try {
				return (StatementObserver) impl.getConstructor().newInstance();
			}
			catch (Exception e) {
				throw new RuntimeException( "Unable to instantiate StatementObserver - " + impl.getName(), e );
			}
		}

		try {
			var namedImpl = Class.forName( setting.toString() );
			return (StatementObserver) namedImpl.getConstructor().newInstance();
		}
		catch (Exception e) {
			throw new RuntimeException( "Unable to instantiate StatementObserver - " + setting, e );
		}
	}

	@Nullable
	private TimeZone getJdbcTimeZone(Object jdbcTimeZoneValue) {
		if ( jdbcTimeZoneValue instanceof TimeZone timeZone ) {
			return timeZone;
		}
		else if ( jdbcTimeZoneValue instanceof ZoneId zoneId ) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Add a public no-argument constructor to the observer class
  2. Read the nested cause: InvocationTargetException means the constructor body threw — fix that exception
  3. Prefer passing a fully-built StatementObserver instance via SessionFactoryBuilder#applyStatementObserver (or the setting) instead of a Class, so construction is under your control
  4. Keep construction side-effect free and resolve collaborators lazily

Example fix

// before:
props.put("hibernate.statement_observer", MetricsObserver.class);
// MetricsObserver only has MetricsObserver(MeterRegistry registry)

// after: pass a ready instance
MeterRegistry registry = Metrics.registries();
props.put("hibernate.statement_observer", new MetricsObserver(registry));
Defensive patterns

Strategy: validation

Validate before calling

// if you register a Class, verify its constructor shape first
static boolean hasPublicNoArgCtor(Class<?> c) {
    try { return Modifier.isPublic(c.getConstructor().getModifiers()); }
    catch (NoSuchMethodException e) { return false; }
}

if (!hasPublicNoArgCtor(MetricsObserver.class)) throw new IllegalStateException("observer needs public no-arg ctor");
props.put("hibernate.statement_observer", MetricsObserver.class);

Type guard

static boolean isStatementObserverSettingValid(Object value) {
    if (value instanceof StatementObserver || value == null) return true;
    if (value instanceof Class<?> c) return StatementObserver.class.isAssignableFrom(c) && hasPublicNoArgCtor(c);
    return false; // strings handled by Class.forName path
}

Try / catch

try {
    sessionFactory = new Configuration().addProperties(props).buildSessionFactory();
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Unable to instantiate StatementObserver")) {
        // fix config; e.getCause() tells why construction failed
    }
    throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/11bd8c31431b92c2. Report an issue: GitHub.