hibernate/hibernate-orm · error · ServiceDependencyException

Cannot inject dependency service

Error message

Cannot inject dependency service

What it means

After resolving a dependent service, Hibernate invokes the @InjectService setter via reflection (Method.invoke). Any failure — usually the setter itself throwing (InvocationTargetException), or an access/type mismatch — is wrapped as ServiceDependencyException("Cannot inject dependency service") with the real cause attached. The injection target code is the first place to look.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/service/internal/AbstractServiceRegistryImpl.java:329

			@Nonnull Method injectionMethod,
			@Nonnull InjectService injectService,
			@Nonnull Class<? extends Service> dependentServiceRole) {
		// todo : because of the use of proxies, this is no longer returning null here...

		final var dependantService = getService( dependentServiceRole );
		if ( dependantService == null ) {
			if ( injectService.required() ) {
				throw new ServiceDependencyException(
						"Dependency [" + dependentServiceRole + "] declared by service [" + service + "] not found"
				);
			}
		}
		else {
			try {
				injectionMethod.invoke( service, dependantService );
			}
			catch ( Exception e ) {
				throw new ServiceDependencyException( "Cannot inject dependency service", e );
			}
		}
	}

	private static Class<? extends Service> dependentServiceRole(
			@Nonnull Method injectionMethod,
			@Nonnull InjectService injectService) {
		final var parameterTypes = injectionMethod.getParameterTypes();
		if ( injectionMethod.getParameterCount() != 1 ) {
			throw new ServiceDependencyException(
					"Encountered @InjectService on method with unexpected number of parameters"
			);
		}

		final var dependentServiceRole = injectService.serviceRole();
		if ( dependentServiceRole == null
				|| Void.class.equals( dependentServiceRole )  // old default value
				|| Service.class.equals( dependentServiceRole ) ) {  // new default value

View on GitHub (pinned to fad1729dce)

Solutions

  1. Unwrap and read the InvocationTargetException cause — it names the failing line inside your setter
  2. Keep @InjectService setters public and trivial: assign the field, nothing else
  3. Match the setter parameter type to the service role interface exactly
  4. Move validation logic out of the setter into the service's start()/post-injection phase

Example fix

// before
@InjectService
public void setJdbcServices(JdbcServices jdbcServices) {
    Objects.requireNonNull(jdbcServices.getDialect()); // throws -> 'Cannot inject dependency service'
    this.jdbcServices = jdbcServices;
}

// after
@InjectService
public void setJdbcServices(JdbcServices jdbcServices) {
    this.jdbcServices = jdbcServices; // validate later, in start()
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
    registry.requireService(MyService.class);
}
catch (ServiceDependencyException e) {
    Throwable inner = e.getCause(); // InvocationTargetException -> your setter's exception
    Throwable real = inner instanceof InvocationTargetException ite ? ite.getTargetException() : inner;
    throw new IllegalStateException("injection setter failed: " + real, real);
}

Prevention

When it happens

Trigger: An @InjectService setter that throws during assignment (e.g., null-checking or validation logic inside the setter); a non-public setter that reflection cannot invoke on the runtime's module rules; a parameter type that does not match the resolved service instance.

Common situations: Setters with defensive logic that rejects the injected instance; JDK/module access restrictions in JPMS or GraalVM native images; service implementations whose concrete type differs from the setter parameter after refactors.

Related errors


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