quarkusio/quarkus · error · DefinitionException

Bean constructor must not have an @Observes parameter:

Error message

Bean constructor must not have an @Observes parameter: 

What it means

ArC throws this DefinitionException at build time when a bean constructor declares a parameter annotated with @Observes. Observer method parameters belong only on @Observes methods; constructors may only declare injection points. The CDI spec forbids observer annotations on bean constructors, and Injection.forBean enforces this while scanning the constructor's parameter annotations.

Source

Thrown at independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java:234

                    transformer, false, new HashSet<>());

            Set<AnnotationTarget> injectConstructors = injections.stream().filter(Injection::isConstructor)
                    .map(Injection::getTarget).collect(Collectors.toSet());
            if (injectConstructors.size() > 1) {
                throw new DefinitionException(
                        "Multiple @Inject constructors found on " + beanTarget.asClass().name() + ":\n"
                                + injectConstructors.stream().map(Object::toString).collect(Collectors.joining("\n")));
            }
            for (AnnotationTarget injectConstructor : injectConstructors) {
                Set<AnnotationInstance> parameterAnnotations = Annotations.getParameterAnnotations(beanDeployment,
                        injectConstructor.asMethod());
                for (AnnotationInstance annotation : parameterAnnotations) {
                    if (DotNames.DISPOSES.equals(annotation.name())) {
                        throw new DefinitionException(
                                "Bean constructor must not have a @Disposes parameter: " + injectConstructor);
                    }
                    if (DotNames.OBSERVES.equals(annotation.name())) {
                        throw new DefinitionException(
                                "Bean constructor must not have an @Observes parameter: " + injectConstructor);
                    }
                    if (DotNames.OBSERVES_ASYNC.equals(annotation.name())) {
                        throw new DefinitionException(
                                "Bean constructor must not have an @ObservesAsync parameter: " + injectConstructor);
                    }
                }
            }

            Set<MethodInfo> initializerMethods = injections.stream()
                    .filter(it -> it.isMethod() && !it.isConstructor())
                    .map(Injection::getTarget)
                    .map(AnnotationTarget::asMethod)
                    .collect(Collectors.toSet());
            for (MethodInfo initializerMethod : initializerMethods) {
                if (beanDeployment.hasAnnotation(initializerMethod, DotNames.PRODUCES)) {
                    throw new DefinitionException("Initializer method must not be annotated @Produces "
                            + "(alternatively, producer method must not be annotated @Inject): "

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove @Observes from the constructor parameter
  2. Add a dedicated observer method: void onEvent(@Observes MyEvent e) { ... } inside the bean
  3. Inject the event payload type as a normal injection point if you actually need it in the constructor
  4. Rebuild; the exception is raised during Quarkus augmentation, not at runtime

Example fix

// before
@Inject
MyBean(@Observes StartupEvent e) { ... }

// after
@Inject
MyBean() { }

void onStart(@Observes StartupEvent e) { ... }
Defensive patterns

Strategy: validation

Validate before calling

void checkConstructor(Method ctor) throws Exception {
    for (var p : ctor.getParameters()) {
        if (p.isAnnotationPresent(jakarta.enterprise.event.Observes.class)) {
            throw new IllegalStateException("@Observes on constructor param: " + ctor);
        }
    }
}

Prevention

When it happens

Trigger: Annotating a parameter of a bean's @Inject constructor with @jakarta.enterprise.event.Observes (or @Observes(priority)), so ArC detects DotNames.OBSERVES on the constructor while processing inject constructors in forBean.

Common situations: Developer intends the bean to receive events and mistakenly puts @Observes on the constructor parameter; refactoring an observer method into a constructor; auto-generated constructor stubs that kept an @Observes parameter.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/644c6c26a8d2f74c. Report an issue: GitHub.