quarkusio/quarkus · error · DeploymentException
${exceptionMsgSupplier.get()} (blocking annotations conflict
Error message
${exceptionMsgSupplier.get()} (blocking annotations conflict) What it means
A gRPC method declares both @Blocking and @NonBlocking (annotation conflict detected in nonInheritedBlockingMode). Quarkus cannot decide the execution model, so the build fails. The same message format is used for any blocking-annotations conflict supplied by the caller.
Source
Thrown at extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/GrpcServerProcessor.java:498
VIRTUAL_THREAD(true),
NON_BLOCKING(false),
// @Transactional on a method
IMPLICIT(true);
final boolean blocking;
BlockingMode(boolean blocking) {
this.blocking = blocking;
}
}
private static BlockingMode nonInheritedBlockingMode(Predicate<DotName> checker,
Supplier<String> exceptionMsgSupplier) {
boolean blocking = checker.test(BLOCKING);
boolean nonBlocking = checker.test(NON_BLOCKING);
boolean vt = checker.test(RUN_ON_VIRTUAL_THREAD);
if (blocking && nonBlocking) {
throw new DeploymentException(exceptionMsgSupplier.get());
}
if (nonBlocking && vt) {
throw new DeploymentException(exceptionMsgSupplier.get());
}
if (blocking && !vt) {
return BlockingMode.BLOCKING;
}
if (vt) {
return BlockingMode.VIRTUAL_THREAD;
}
if (nonBlocking) {
return BlockingMode.NON_BLOCKING;
}
boolean transactional = checker.test(TRANSACTIONAL);
if (transactional) { // Cannot be on a virtual thread here.
return BlockingMode.IMPLICIT;
}
return BlockingMode.UNDEFINED;View on GitHub (pinned to e1c734241f)
Solutions
- Keep only one of @Blocking/@NonBlocking on the method (or its class)
- Use @NonBlocking with @RunOnVirtualThread only if that is intended (see related error)
- Check inherited annotations from implemented service interfaces for the conflicting annotation
Example fix
// before
@Blocking
@NonBlocking
public void greet(...) { ... }
// after
@Blocking
public void greet(...) { ... } Defensive patterns
Strategy: validation
Validate before calling
// review annotations before build
if (m.isAnnotationPresent(Blocking.class) && m.isAnnotationPresent(NonBlocking.class)) {
throw new IllegalStateException("Choose either @Blocking or @NonBlocking: " + m);
} Prevention
- Pick one execution-model annotation per method
- Audit inherited annotations from service interfaces
- Document the project convention for blocking vs non-blocking methods
When it happens
Trigger: @Blocking and @NonBlocking are both present on the same gRPC service method (via method, class, or interface inheritance through the checker predicate).
Common situations: Copy-pasting blocking style annotations while also adding @NonBlocking; class-level @Blocking combined with a method-level @NonBlocking intent written as both; merging branches that each added a different annotation.
Related errors
- ${exceptionMsgSupplier.get()} (nonBlocking/virtual-thread an
- Blocking gRPC client call made from the event loop. If the c
- Stateless operations not supported
- Cannot attach headers to a null client
- Unsupported client type " + client.getClass()
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/86ad0ef8354d6f4f.
Report an issue: GitHub.