quarkusio/quarkus · error · DeploymentException
Method '' of class '' contains both @Blocking and…
Error message
Method '' of class '' contains both @Blocking and @NonBlocking annotations.
What it means
A method cannot be annotated with both @Blocking and @NonBlocking — the desired execution model would be ambiguous. EndpointIndexer detects the conflict and throws this DeploymentException when both annotations target the same method (same annotation target kind METHOD).
Solutions
- Remove the @NonBlocking annotation from the method, keeping @Blocking
- Or remove @Blocking and keep @NonBlocking if the method is reactive
- Decide one execution model per method based on whether it performs blocking I/O
Example fix
// before
@Blocking
@NonBlocking
public String get() { ... }
// after
@Blocking
public String get() { ... } Defensive patterns
Strategy: validation
Validate before calling
Method m = MyResource.class.getMethod("get");
if (m.isAnnotationPresent(Blocking.class) && m.isAnnotationPresent(NonBlocking.class)) {
throw new IllegalStateException("Both @Blocking and @NonBlocking on " + m);
} Prevention
- Choose one execution model per method: blocking I/O => @Blocking, reactive => @NonBlocking
- Watch for copy-paste and merge conflicts around threading annotations
- Check superclass/interface annotations that may conflict via inheritance
- Add CI annotation-scanning tests for resource classes
When it happens
Trigger: Deploying a resource method that (after annotation inheritance/inheritable lookup) resolves to having both a @Blocking and a @NonBlocking annotation directly on the method.
Common situations: Copy-pasting annotations from another endpoint; a merge conflict leaving both annotations in place; IDE auto-import adding @NonBlocking next to an existing @Blocking while experimenting with threading behavior.
Related errors
- Class '' contains both @Blocking and @NonBlocking…
- Endpoints that produce a Multipart result can only be used…
- Method '' of class '' is considered a non blocking method…
- Cannot handle wildcard type
- Cannot have more than one of @PathParam, @QueryParam…
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/30ddd7a5769ec689.
Report an issue: GitHub.
Appendix: source
Thrown at independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java:922
if (blockingAnnotation != null) {
return false;
} else {
return defaultValue == BlockingDefault.RUN_ON_VIRTUAL_THREAD;
}
}
}
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;View on GitHub (pinned to e1c734241f)