{"record":{"id":"04f1b6381c4b37de","repo":"quarkusio/quarkus","slug":"clientredirecthandler-is-only-supported-on-static","errorCode":null,"errorMessage":"@ClientRedirectHandler is only supported on static methods of REST Client interfaces that take 'jakarta.ws.rs.core.Response' as a single parameter and return 'java.net.URI'. Offending instance is '${className}#${methodName}'","messagePattern":"@ClientRedirectHandler is only supported on static methods of REST Client interfaces that take 'jakarta\\.ws\\.rs\\.core\\.Response' as a single parameter and return 'java\\.net\\.URI'\\. Offending instance is '(.+?)#(.+?)'","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/ClientRedirectHandler.java","lineNumber":87,"sourceCode":"                    boolean returnsUri = URI.class.isAssignableFrom(\n                            Class.forName(returnTypeClassName, false, Thread.currentThread().getContextClassLoader()));\n                    if (returnsUri) {\n                        isValid = true;\n                    }\n                } catch (ClassNotFoundException ignored) {\n\n                }\n            }\n        }\n        if (!isValid) {\n            String message = DotNames.CLIENT_REDIRECT_HANDLER\n                    + \" is only supported on static methods of REST Client interfaces that take 'jakarta.ws.rs.core.Response'\"\n                    + \" as a single parameter and return 'java.net.URI'.\";\n            if (targetMethod != null) {\n                message += \" Offending instance is '\" + targetMethod.declaringClass().name().toString() + \"#\"\n                        + targetMethod.name() + \"'\";\n            }\n            throw new IllegalStateException(message);\n        }\n\n        StringBuilder sigBuilder = new StringBuilder();\n        sigBuilder.append(targetMethod.name()).append(\"_\").append(targetMethod.returnType().name().toString());\n        for (Type i : targetMethod.parameterTypes()) {\n            sigBuilder.append(i.name().toString());\n        }\n\n        int priority = Priorities.USER;\n        AnnotationValue priorityAnnotationValue = instance.value(\"priority\");\n        if (priorityAnnotationValue != null) {\n            priority = priorityAnnotationValue.asInt();\n        }\n\n        ClassInfo restClientInterfaceClassInfo = targetMethod.declaringClass();\n        String generatedClassName = restClientInterfaceClassInfo.name().toString() + \"_\" + targetMethod.name() + \"_\"\n                + \"ResponseRedirectHandler\" + \"_\" + HashUtil.sha1(sigBuilder.toString());\n        final MethodInfo target = targetMethod;","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/ClientRedirectHandler.java#L69-L105","documentation":"@ClientRedirectHandler annotates a static method that decides a redirect URI from a failed Response. Quarkus enforces the exact contract: static method, single jakarta.ws.rs.core.Response parameter, java.net.URI return type. This IllegalStateException fails the build when the annotated method violates it.","triggerScenarios":"@ClientRedirectHandler method that is non-static, has no or extra parameters, does not take Response, or returns String/void/other instead of java.net.URI.","commonSituations":"Returning a String URL instead of URI; adding a second parameter for context; copy-pasting an @ClientExceptionMapper method and changing only the annotation.","solutions":["Change the method to accept exactly one jakarta.ws.rs.core.Response and return java.net.URI","Make the method static and keep it in the REST client interface","Convert String URLs with URI.create(...) before returning"],"exampleFix":"// before\n@ClientRedirectHandler\nstatic String redirect(Response r) { return \"/login\"; }\n// after\n@ClientRedirectHandler\nstatic java.net.URI redirect(Response r) {\n    return java.net.URI.create(\"/login\");\n}","handlingStrategy":"validation","validationCode":"static boolean validRedirectHandler(Method m) {\n    return Modifier.isStatic(m.getModifiers())\n        && m.getParameterCount() == 1\n        && m.getParameterTypes()[0] == jakarta.ws.rs.core.Response.class\n        && m.getReturnType() == java.net.URI.class;\n}","typeGuard":null,"tryCatchPattern":"try {\n    handler.generateResponseExceptionMapper(classResult, instance);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"ClientRedirectHandler\")) { /* fix to (Response)->URI */ }\n    throw e;\n}","preventionTips":["Use exact signature: static java.net.URI name(jakarta.ws.rs.core.Response r)","Convert String URLs with URI.create(...) inside the method","Do not add extra parameters for context"],"tags":["rest-client","redirect-handler","annotation-processing","build-time"],"backgroundTag":"rest-client-annotation-misuse","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"}