spring-projects/spring-framework · error · IllegalStateException
Lifecycle annotation requires a no-arg method: {}
Error message
Lifecycle annotation requires a no-arg method: {} What it means
A method carrying a lifecycle annotation (@PostConstruct/@PreDestroy or a custom one configured on InitDestroyAnnotationBeanPostProcessor) declares one or more parameters. Spring requires lifecycle methods to be no-arg, verified in the LifecycleMethod constructor before the method is registered. This is a configuration/programming error detected at bean-class introspection time.
Source
Thrown at spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java:436
Collection<LifecycleMethod> destroyMethodsToUse =
(checkedDestroyMethods != null ? checkedDestroyMethods : this.destroyMethods);
return !destroyMethodsToUse.isEmpty();
}
}
/**
* Class representing an annotated init or destroy method.
*/
private static class LifecycleMethod {
private final Method method;
private final String identifier;
public LifecycleMethod(Method method, Class<?> beanClass) {
if (method.getParameterCount() != 0) {
throw new IllegalStateException("Lifecycle annotation requires a no-arg method: " + method);
}
this.method = method;
this.identifier = (isPrivateOrNotVisible(method, beanClass) ?
ClassUtils.getQualifiedMethodName(method) : method.getName());
}
public Method getMethod() {
return this.method;
}
public String getIdentifier() {
return this.identifier;
}
public void invoke(Object target) throws Throwable {
ReflectionUtils.makeAccessible(this.method);
this.method.invoke(target);
}View on GitHub (pinned to e8729d0438)
Solutions
- Remove all parameters from the @PostConstruct/@PreDestroy method so its signature is void-compatible with zero args.
- If you need a collaborator, inject it as a field or constructor argument and reference it from the no-arg lifecycle method.
- If you intended a different method, move the annotation to the correct no-arg method.
Example fix
// before
@PostConstruct
public void init(DataSource ds) { /* wrong */ }
// after
@Autowired
private DataSource ds;
@PostConstruct
public void init() { ds.getConnection(); } Defensive patterns
Strategy: validation
Validate before calling
ReflectionUtils.doWithMethods(beanType, m -> {
if (m.isAnnotationPresent(PostConstruct.class) || m.isAnnotationPresent(PreDestroy.class)) {
if (m.getParameterCount() != 0) throw new IllegalStateException(
m + " must be no-arg to qualify as a lifecycle method");
}
}); Type guard
boolean isNoArgLifecycle(Method m) {
return (m.isAnnotationPresent(PostConstruct.class)
|| m.isAnnotationPresent(PreDestroy.class))
&& m.getParameterCount() == 0;
} Prevention
- Treat @PostConstruct/@PreDestroy as void, zero-arg methods by convention.
- Add a test that scans bean classes for lifecycle annotations and asserts zero parameters.
- Inject collaborators via field/constructor, never via lifecycle-method parameters.
When it happens
Trigger: Annotating a method that takes arguments with @PostConstruct or @PreDestroy (or the custom init/destroy annotation type set via setInitAnnotationType/setDestroyAnnotationType). The check fails immediately when the bean class is scanned for lifecycle methods.
Common situations: Developer adds a parameter to a @PostConstruct method (e.g. to inject a collaborator positionally), copies a pattern from another framework that allows args, or uses a custom lifecycle annotation on an existing business method that happens to take parameters.
Related errors
- Invocation of init method failed
- Failed to invoke init method
- Value annotation must have a value attribute
- Cannot invoke instance method without factoryBeanName: {}
- No StringValueResolver specified - pass a resolver object in
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/17ae9f633177a6a9.json.
Report an issue: GitHub.