quarkusio/quarkus · error · DeploymentException

Class '' contains both @Blocking and @NonBlocking annotation

Error message

Class '' contains both @Blocking and @NonBlocking annotations.

What it means

A class cannot declare both @Blocking and @NonBlocking — the default execution model for all its methods would be ambiguous. When EndpointIndexer finds both annotations on the class (same target kind CLASS, not METHOD), deployment fails with this DeploymentException.

Source

Thrown at independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java:926

            }
        }
    }

    private boolean isBlocking(MethodInfo info, BlockingDefault defaultValue) {
        Map.Entry<AnnotationTarget, AnnotationInstance> blockingAnnotation = getInheritableAnnotation(info, BLOCKING);
        Map.Entry<AnnotationTarget, AnnotationInstance> runOnVirtualThreadAnnotation = getInheritableAnnotation(info,
                RUN_ON_VIRTUAL_THREAD);
        Map.Entry<AnnotationTarget, AnnotationInstance> nonBlockingAnnotation = getInheritableAnnotation(info,
                NON_BLOCKING);

        if ((blockingAnnotation != null) && (nonBlockingAnnotation != null)) {
            if (blockingAnnotation.getKey().kind() == nonBlockingAnnotation.getKey().kind()) {
                if (blockingAnnotation.getKey().kind() == AnnotationTarget.Kind.METHOD) {
                    throw new DeploymentException(
                            "Method '" + info.name() + "' of class '" + info.declaringClass().name()
                                    + "' contains both @Blocking and @NonBlocking annotations.");
                } else {
                    throw new DeploymentException("Class '" + info.declaringClass().name()
                            + "' contains both @Blocking and @NonBlocking annotations.");
                }
            }
            if (blockingAnnotation.getKey().kind() == AnnotationTarget.Kind.METHOD) {
                // the most specific annotation was the @Blocking annotation on the method
                return true;
            } else {
                // the most specific annotation was the @NonBlocking annotation on the method
                return false;
            }
        } else if ((blockingAnnotation != null)) {
            return true;
        } else if ((nonBlockingAnnotation != null)) {
            return false;
        }

        if (defaultValue == BlockingDefault.BLOCKING) {
            return true;

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove @NonBlocking from the class, keeping @Blocking as the class default
  2. Or remove @Blocking and keep @NonBlocking if the endpoints are reactive
  3. Move the specific annotation to individual methods instead of mixing at class level

Example fix

// before
@Blocking
@NonBlocking
@Path("/items")
public class ItemResource { ... }
// after
@Blocking
@Path("/items")
public class ItemResource { ... }
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = MyResource.class;
if (c.isAnnotationPresent(Blocking.class) && c.isAnnotationPresent(NonBlocking.class)) {
    throw new IllegalStateException("Both @Blocking and @NonBlocking on class " + c.getName());
}
// also check superclasses/interfaces for inherited conflicts
Class<?> s = c.getSuperclass();
while (s != null && s != Object.class) {
    if (s.isAnnotationPresent(Blocking.class) && c.isAnnotationPresent(NonBlocking.class))
        throw new IllegalStateException("Inherited @Blocking conflicts with class @NonBlocking");
    s = s.getSuperclass();
}

Prevention

When it happens

Trigger: Deploying a resource class annotated with both @Blocking and @NonBlocking at class level; annotations inherited from a superclass/interface that together yield both.

Common situations: Class-level annotation experimentation left in place; inheritance from a base resource class that carries the opposite annotation; bulk refactoring applying @NonBlocking to a class already marked @Blocking.

Related errors


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