{"record":{"id":"f01947bfb943aee5","repo":"quarkusio/quarkus","slug":"suspend-method-targetmethod-name-of-class-f01947","errorCode":null,"errorMessage":"Suspend method '${targetMethod.name()} of class '${targetMethod.declaringClass().name()}' cannot be used as a request filter as it does not declare 'void' as its return type.","messagePattern":"Suspend method '(.+?) of class '(.+?)' cannot be used as a request filter as it does not declare 'void' as its return type\\.","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/generation/filters/CustomFilterGenerator.java","lineNumber":382,"sourceCode":"                        + \"' is not allowed\");\n            }\n        }\n        return targetMethodParamHandles;\n    }\n\n    String generateContainerResponseFilter(MethodInfo targetMethod, ClassOutput classOutput) {\n        checkModifiers(targetMethod, ResteasyReactiveServerDotNames.SERVER_RESPONSE_FILTER);\n        if (KotlinUtils.isSuspendMethod(targetMethod)) {\n            return generateResponseFilterForSuspendedMethod(targetMethod, classOutput, isOptionalFilter.test(targetMethod));\n        }\n        return generateStandardContainerResponseFilter(targetMethod, classOutput, isOptionalFilter.test(targetMethod));\n    }\n\n    private String generateResponseFilterForSuspendedMethod(MethodInfo targetMethod, ClassOutput classOutput,\n            boolean checkForOptionalBean) {\n        DotName returnDotName = determineReturnDotNameOfSuspendMethod(targetMethod);\n        if (!returnDotName.equals(VOID)) {\n            throw new RuntimeException(\"Suspend method '\" + targetMethod.name() + \" of class '\"\n                    + targetMethod.declaringClass().name()\n                    + \"' cannot be used as a request filter as it does not declare 'void' as its return type.\");\n        }\n        String generatedClassName = getGeneratedClassName(targetMethod, ResteasyReactiveServerDotNames.SERVER_RESPONSE_FILTER);\n        ClassInfo declaringClass = targetMethod.declaringClass();\n        DotName declaringClassName = declaringClass.name();\n        try (ClassCreator cc = ClassCreator.builder().classOutput(classOutput)\n                .className(generatedClassName)\n                .superClass(ABSTRACT_SUSPENDED_RES_FILTER)\n                .build()) {\n            FieldDescriptor delegateField = generateConstructorAndDelegateField(cc, declaringClass,\n                    ABSTRACT_SUSPENDED_RES_FILTER, additionalBeanAnnotations, checkForOptionalBean);\n\n            // generate the implementation of the filter method\n            MethodCreator doFilterMethod = cc.getMethodCreator(\"doFilter\", Object.class.getName(),\n                    ResteasyReactiveContainerRequestContext.class.getName(), ContainerResponseContext.class.getName(),\n                    ResteasyReactiveDotNames.CONTINUATION.toString());\n","sourceCodeStart":364,"sourceCodeEnd":400,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/generation/filters/CustomFilterGenerator.java#L364-L400","documentation":"generateResponseFilterForSuspendedMethod handles Kotlin suspend @ServerResponseFilter methods. It unwraps the Continuation return type and requires it to be void (Unit in Kotlin); response filters must not return a value — they mutate the ContainerResponseContext or return via the context. A non-void result throws this RuntimeException (note the message says 'request filter' due to a copied message string, but it is raised for response filters).","triggerScenarios":"A Kotlin suspend fun annotated with @ServerResponseFilter whose return type after Continuation unwrapping is not void/Unit — e.g. suspend fun filter(ctx: ContainerResponseContext): Response.","commonSituations":"Kotlin developers returning the (possibly modified) response from suspend response filters, assuming return-based mutation like request filters allow with Response.","solutions":["Change the suspend response filter to return Unit and mutate ContainerResponseContext (e.g. setEntity, setStatus) instead of returning a value","Use a non-suspend response filter returning void if no suspension is needed","Remove @ServerResponseFilter if the method is not a response filter"],"exampleFix":"// before (Kotlin)\n@ServerResponseFilter\nsuspend fun filter(response: ContainerResponseContext): Response { ... }\n\n// after\n@ServerResponseFilter\nsuspend fun filter(response: ContainerResponseContext) {\n    response.statusInfo = Response.Status.OK\n}","handlingStrategy":"validation","validationCode":"// Kotlin: suspend response filter must return Unit\nval m = clazz.declaredMethods.first { it.isAnnotationPresent(ServerResponseFilter::class.java) }\nif (m.kotlinFunction?.isSuspend == true && m.returnType != Void.TYPE) {\n    throw new IllegalStateException(\"Suspend response filter must return Unit: $m\")\n}\n","typeGuard":"fun isValidSuspendResponseFilter(m: Method): Boolean = m.returnType == Void.TYPE\n","tryCatchPattern":null,"preventionTips":["Kotlin suspend response filters must return Unit — mutate ContainerResponseContext instead of returning","Do not copy suspend request filter signatures (which may return Response) to response filters","Follow the Quarkus Kotlin filters documentation examples verbatim"],"tags":["quarkus","resteasy-reactive","kotlin","response-filter","build-time"],"backgroundTag":"invalid-filter-signature","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"}