spring-projects/spring-framework · error · BeanCreationException

Failed to invoke init method

Error message

Failed to invoke init method

What it means

Thrown by the same init-method invocation path as error 200, but this branch catches a generic Throwable (not InvocationTargetException), meaning the failure is at the reflection/invocation level rather than inside the user's init method body. Typical causes are illegal access, the method disappearing, or an Error (e.g. NoClassDefFoundError, StackOverflowError) raised while setting up the call.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java:223

	private static String[] safeMerge(String @Nullable [] existingNames, Collection<LifecycleMethod> detectedMethods) {
		Stream<String> detectedNames = detectedMethods.stream().map(LifecycleMethod::getIdentifier);
		Stream<String> mergedNames = (existingNames != null ?
				Stream.concat(detectedNames, Stream.of(existingNames)) : detectedNames);
		return mergedNames.distinct().toArray(String[]::new);
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
		try {
			metadata.invokeInitMethods(bean, beanName);
		}
		catch (InvocationTargetException ex) {
			throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
		}
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	@Override
	public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
		LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
		try {
			metadata.invokeDestroyMethods(bean, beanName);
		}
		catch (InvocationTargetException ex) {
			String msg = "Destroy method on bean with name '" + beanName + "' threw an exception";
			if (logger.isDebugEnabled()) {

View on GitHub (pinned to e8729d0438)

Solutions

  1. Read the wrapped Throwable (not just the message) - it identifies the invocation-level failure (NoClassDefFoundError, IllegalAccessException, etc.).
  2. If a missing class/type: align dependency versions between compile and runtime classpath.
  3. If an access error: ensure the init method is non-private or that the package is open/exports the type (Java modules), or make it package-private with makeAccessible allowed.
  4. If a static-init failure: fix the static initializer block that the method transitively triggers.

Example fix

// before
@PostConstruct
private void init() { /* IllegalAccessException on some classloaders */ }
// after
@PostConstruct
void init() { /* package-private, accessible */ }
Defensive patterns

Strategy: validation

Validate before calling

for (String name : context.getBeanDefinitionNames()) {
  BeanDefinition bd = context.getBeanFactory().getBeanDefinition(name);
  if (bd.getBeanClassName() != null) {
    Class<?> c = ClassUtils.forName(bd.getBeanClassName(), context.getClassLoader());
    ReflectionUtils.doWithMethods(c, m -> {
      if (m.isAnnotationPresent(PostConstruct.class) && !Modifier.isAccessible(m)) {
        log.warn("Inaccessible @PostConstruct on {}", name);
      }
    });
  }
}

Try / catch

try { context.refresh(); }
catch (BeanCreationException ex) {
  Throwable cause = ex.getCause(); // not InvocationTargetException - the raw throwable
  if (cause instanceof NoClassDefFoundError || cause instanceof IllegalAccessException) {
    log.error("Classpath/access mismatch for init method", cause);
  }
  throw ex;
}

Prevention

When it happens

Trigger: invokeInitMethods throws something that is not an InvocationTargetException - e.g. IllegalAccessException because the init method became inaccessible, NoClassDefFoundError for a type referenced by the method, or an ExceptionInInitializerError from a static block the method triggers.

Common situations: Bean class compiled against a different version of a dependency than what is on the runtime classpath; classloader/visibility issues in shaded or modular apps; a static initializer in the bean class failing; reflective access denied under a strict module boundary (Java modules).

Related errors


AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04). Data as JSON: /data/errors/ca82931f2a543192.json. Report an issue: GitHub.