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

  1. Keep only one of @Blocking/@NonBlocking on the method (or its class)
  2. Use @NonBlocking with @RunOnVirtualThread only if that is intended (see related error)
  3. 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

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


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