hibernate/hibernate-orm · error · ServiceDependencyException

Encountered @InjectService on method with unexpected number

Error message

Encountered @InjectService on method with unexpected number of parameters

What it means

Hibernate's dependency scanner only accepts @InjectService on methods with exactly one parameter (the dependent service). dependentServiceRole() throws ServiceDependencyException at registry build time when it finds an annotated method with zero or two-plus parameters. This is a pure programming-error guard for code implementing Hibernate's service SPI.

Source

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

				);
			}
		}
		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
			return (Class<? extends Service>) parameterTypes[0];
		}
		else {
			return dependentServiceRole;
		}
	}

	@Override
	public <R extends Service> void startService(ServiceBinding<R> serviceBinding) {
		if ( serviceBinding.getService() instanceof Startable startable ) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Change the annotated method to take exactly one parameter of the dependency type
  2. If the role differs from the parameter type, specify it: @InjectService(serviceRole = MyRole.class)
  3. Add a startup smoke test that builds the registry so signature errors fail the build, not production boot

Example fix

// before
@InjectService
public void configure(JdbcServices jdbcServices, ClassLoaderService cls) { ... } // 2 params

// after
@InjectService
public void setJdbcServices(JdbcServices jdbcServices) { this.jdbcServices = jdbcServices; }

@InjectService
public void setClassLoaderService(ClassLoaderService cls) { this.cls = cls; }
Defensive patterns

Strategy: validation

Validate before calling

// startup self-check for service classes you ship
for (Method m : MyService.class.getDeclaredMethods()) {
    if (m.isAnnotationPresent(InjectService.class)
            && m.getParameterCount() != 1) {
        throw new IllegalStateException(
            "@InjectService on non-single-arg method: " + m);
    }
}

Type guard

boolean isValidInjectServiceMethod(Method m) {
    return m.isAnnotationPresent(InjectService.class) && m.getParameterCount() == 1;
}

Prevention

When it happens

Trigger: Annotating an overloaded convenience method, a method taking extra context arguments, or (mistakenly, since only methods are scanned) expecting field injection semantics; copy-pasting @InjectService onto a lifecycle method with multiple parameters.

Common situations: Writing a custom org.hibernate.service.Service without following the setter-injection convention; refactoring a single-arg setter into a multi-arg method while leaving the annotation.

Related errors


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