{"record":{"id":"f85b7b74c81c028f","repo":"quarkusio/quarkus","slug":"class-contains-both-blocking-and-nonblocking","errorCode":null,"errorMessage":"Class '' contains both @Blocking and @NonBlocking annotations.","messagePattern":"Class '' contains both @Blocking and @NonBlocking annotations\\.","errorType":"validation","errorClass":"DeploymentException","httpStatus":null,"severity":"error","filePath":"independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java","lineNumber":926,"sourceCode":"            }\n        }\n    }\n\n    private boolean isBlocking(MethodInfo info, BlockingDefault defaultValue) {\n        Map.Entry<AnnotationTarget, AnnotationInstance> blockingAnnotation = getInheritableAnnotation(info, BLOCKING);\n        Map.Entry<AnnotationTarget, AnnotationInstance> runOnVirtualThreadAnnotation = getInheritableAnnotation(info,\n                RUN_ON_VIRTUAL_THREAD);\n        Map.Entry<AnnotationTarget, AnnotationInstance> nonBlockingAnnotation = getInheritableAnnotation(info,\n                NON_BLOCKING);\n\n        if ((blockingAnnotation != null) && (nonBlockingAnnotation != null)) {\n            if (blockingAnnotation.getKey().kind() == nonBlockingAnnotation.getKey().kind()) {\n                if (blockingAnnotation.getKey().kind() == AnnotationTarget.Kind.METHOD) {\n                    throw new DeploymentException(\n                            \"Method '\" + info.name() + \"' of class '\" + info.declaringClass().name()\n                                    + \"' contains both @Blocking and @NonBlocking annotations.\");\n                } else {\n                    throw new DeploymentException(\"Class '\" + info.declaringClass().name()\n                            + \"' contains both @Blocking and @NonBlocking annotations.\");\n                }\n            }\n            if (blockingAnnotation.getKey().kind() == AnnotationTarget.Kind.METHOD) {\n                // the most specific annotation was the @Blocking annotation on the method\n                return true;\n            } else {\n                // the most specific annotation was the @NonBlocking annotation on the method\n                return false;\n            }\n        } else if ((blockingAnnotation != null)) {\n            return true;\n        } else if ((nonBlockingAnnotation != null)) {\n            return false;\n        }\n\n        if (defaultValue == BlockingDefault.BLOCKING) {\n            return true;","sourceCodeStart":908,"sourceCodeEnd":944,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java#L908-L944","documentation":"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.","triggerScenarios":"Deploying a resource class annotated with both @Blocking and @NonBlocking at class level; annotations inherited from a superclass/interface that together yield both.","commonSituations":"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.","solutions":["Remove @NonBlocking from the class, keeping @Blocking as the class default","Or remove @Blocking and keep @NonBlocking if the endpoints are reactive","Move the specific annotation to individual methods instead of mixing at class level"],"exampleFix":"// before\n@Blocking\n@NonBlocking\n@Path(\"/items\")\npublic class ItemResource { ... }\n// after\n@Blocking\n@Path(\"/items\")\npublic class ItemResource { ... }","handlingStrategy":"validation","validationCode":"Class<?> c = MyResource.class;\nif (c.isAnnotationPresent(Blocking.class) && c.isAnnotationPresent(NonBlocking.class)) {\n    throw new IllegalStateException(\"Both @Blocking and @NonBlocking on class \" + c.getName());\n}\n// also check superclasses/interfaces for inherited conflicts\nClass<?> s = c.getSuperclass();\nwhile (s != null && s != Object.class) {\n    if (s.isAnnotationPresent(Blocking.class) && c.isAnnotationPresent(NonBlocking.class))\n        throw new IllegalStateException(\"Inherited @Blocking conflicts with class @NonBlocking\");\n    s = s.getSuperclass();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set the class default once — either @Blocking or @NonBlocking — and override per method only","Audit base resource classes for threading annotations before subclassing","Avoid bulk-annotating whole classes during reactive migrations","Document the class-level threading policy in the API module"],"tags":["quarkus","resteasy-reactive","blocking","nonblocking","class-level","deployment"],"backgroundTag":"conflicting-blocking-annotations","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}