SonarSource/sonarqube · error · IllegalStateException

Constructor annotations missing in:

Error message

Constructor annotations missing in: 

What it means

PriorityBeanFactory overrides Spring's instantiateBean to fail fast when a bean class has more than one constructor but no explicit constructor annotation (@Autowired/@Inject) or XML-specified constructor resolution. With multiple constructors and no annotations, Spring would silently pick the no-arg constructor, so SonarQube refuses to guess and throws IllegalStateException naming the offending class.

Source

Thrown at sonar-core/src/main/java/org/sonar/core/platform/PriorityBeanFactory.java:109

    while (factory != null) {
      if (factory.containsBeanDefinition(beanName)) {
        return i;
      }
      factory = (DefaultListableBeanFactory) factory.getParentBeanFactory();
      i++;
    }
    return null;
  }

  /**
   * A common mistake when migrating from Pico Container to Spring is to forget to add @Inject or @Autowire annotations to classes that have multiple constructors.
   * Spring will fail if there is no default no-arg constructor, but it will silently use the no-arg constructor if there is one, never calling the other constructors.
   * We override this method to fail fast if a class has multiple constructors.
   */
  @Override
  protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
    if (mbd.hasBeanClass() && mbd.getBeanClass().getConstructors().length > 1) {
      throw new IllegalStateException("Constructor annotations missing in: " + mbd.getBeanClass());
    }
    return super.instantiateBean(beanName, mbd);
  }

  private static class Bean {
    private final String name;
    private final Object instance;

    public Bean(String name, Object instance) {
      this.name = name;
      this.instance = instance;
    }

    public String getName() {
      return name;
    }

    public Object getInstance() {

View on GitHub (pinned to 184c821202)

Solutions

  1. Annotate the intended constructor with @org.springframework.beans.factory.annotation.Autowired (or @Inject).
  2. Delete the extra constructor so the class has exactly one constructor.
  3. Register the bean with an explicit constructor-arg definition so instantiateBean's multi-constructor check is not hit.

Example fix

// before
class MyService {
  MyService(Database db) { ... }
  MyService() { ... } // second ctor -> IllegalStateException
}
// after
class MyService {
  @Autowired
  MyService(Database db) { ... }
}
Defensive patterns

Strategy: type-guard

Validate before calling

static boolean isContainerSafe(Class<?> beanClass) {
  return beanClass.getConstructors().length <= 1
    || Arrays.stream(beanClass.getConstructors())
        .anyMatch(c -> c.isAnnotationPresent(Autowired.class) || c.isAnnotationPresent(Inject.class));
}

Type guard

boolean hasSingleOrAnnotatedConstructor(Class<?> c) {
  java.lang.reflect.Constructor<?>[] ctors = c.getConstructors();
  return ctors.length == 1 || Arrays.stream(ctors).anyMatch(k -> k.isAnnotationPresent(Autowired.class));
}

Try / catch

try {
  container.add(MyService.class);
} catch (IllegalStateException e) {
  // e.getMessage() names the offending class: add @Autowired or remove extra constructor
}

Prevention

When it happens

Trigger: Registering a class with 2+ constructors (and no @Autowired on any constructor, no no-arg-only case handled as intended) into a SonarQube Spring container; the bean is instantiated without an explicit constructor definition.

Common situations: Adding a second constructor (e.g. for tests) to a component without adding @Autowired to the intended one; refactoring a component's constructor while keeping the old one for compatibility.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/9b39d56843a53e90. Report an issue: GitHub.