hibernate/hibernate-orm · error · IllegalStateException

BootstrapContext is no longer available

Error message

BootstrapContext is no longer available

What it means

Hibernate hands each Integrator an Integrator.Context; on this implementation getBootstrapContext() deliberately throws IllegalStateException because the BootstrapContext (bootstrap-time services, classmate access, managed beans) is discarded once the SessionFactory is built. The context exposed by IntegratorObserver is only intended for disintegrate() callbacks at factory close. Any integrator that asks for the BootstrapContext after bootstrap will always get this error.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java:545

	}

	@Override
	@Nonnull
	public PlanningOptions getGraphPlanningOptions() {
		return graphPlanningOptions;
	}

	@SuppressWarnings("removal")
	class IntegratorObserver implements SessionFactoryObserver {
		private final Integrator.Context context = new Integrator.Context() {
			@Override
			public ManagedBeanRegistry getManagedBeanRegistry() {
				return SessionFactoryImpl.this.getManagedBeanRegistry();
			}

			@Override
			public BootstrapContext getBootstrapContext() {
				throw new IllegalStateException( "BootstrapContext is no longer available" );
			}
		};
		private final ArrayList<Integrator> integrators = new ArrayList<>();

		@Override
		public void sessionFactoryClosed(SessionFactory factory) {
			for ( var integrator : integrators ) {
				integrator.disintegrate( SessionFactoryImpl.this, context );
			}
			integrators.clear();
		}
	}

	@SuppressWarnings("removal")
	private static Integrator.Context createIntegratorContext(BootstrapContext bootstrapContext) {
		return () -> bootstrapContext;
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Cache everything you need from BootstrapContext (ServiceRegistry, ManagedBeanRegistry, BeanContainer) in fields during integrate(); never call context.getBootstrapContext() in disintegrate()
  2. If you need managed beans at shutdown, use context.getManagedBeanRegistry() which is still supported on this Context implementation
  3. Upgrade the integrator library to a Hibernate 6.2+/7.x compatible build where the new Integrator.Context contract is respected
  4. If you control the code, restructure the integrator so shutdown work only needs the SessionFactoryImplementor passed to disintegrate()

Example fix

// before
@Override
public void disintegrate(SessionFactoryImplementor factory, Integrator.Context context) {
    context.getBootstrapContext().getServiceRegistry(); // IllegalStateException
}

// after
private ServiceRegistry serviceRegistry;

@Override
public void integrate(Metadata metadata, BootstrapContext bootstrapContext,
                       SessionFactoryImplementor sessionFactory) {
    this.serviceRegistry = bootstrapContext.getServiceRegistry(); // capture at bootstrap
}

@Override
public void disintegrate(SessionFactoryImplementor factory, Integrator.Context context) {
    // use the cached serviceRegistry; never call context.getBootstrapContext()
}
Defensive patterns

Strategy: validation

Validate before calling

// In your integrator, gate on a flag you control instead of probing the context
private boolean bootstrapped;

@Override
public void integrate(Metadata md, BootstrapContext ctx, SessionFactoryImplementor sf) {
    this.captured = ctx.getServiceRegistry();
    this.bootstrapped = true;
}

@Override
public void disintegrate(SessionFactoryImplementor sf, Integrator.Context ctx) {
    if (!bootstrapped) return; // integrate never ran; do not touch bootstrap resources
    // use `captured`, never ctx.getBootstrapContext()
}

Try / catch

try {
    // integrator shutdown logic
} catch (IllegalStateException e) {
    // BootstrapContext is gone after bootstrap; fall back to data cached at integrate()
    LOG.warn("bootstrap context unavailable at disintegrate; using cached state", e);
}

Prevention

When it happens

Trigger: An org.hibernate.integrator.spi.Integrator implementation calls context.getBootstrapContext() inside disintegrate(sessionFactory, context), or stores the Integrator.Context and calls getBootstrapContext() after SessionFactoryObserver.sessionFactoryClosed fires. Also hit by integrators ported from older Hibernate versions where disintegrate() used to receive a BootstrapContext parameter.

Common situations: Upgrading a custom integrator from Hibernate 5.x/6.0 to 6.2+/7.x where the disintegrate signature changed to Integrator.Context; third-party integrator libraries (auditing, multi-tenancy, metrics) that still touch bootstrap services at shutdown; integrators that resolve beans via BootstrapContext instead of caching them during integrate().

Related errors


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