{"record":{"id":"3a80776e864f5e02","repo":"quarkusio/quarkus","slug":"can-t-call-update-method-in-a-reactive-context","errorCode":null,"errorMessage":"Can't call `update` method in a Reactive context. Use `getHeaders` or implement ClientHeadersFactory.","messagePattern":"Can't call `update` method in a Reactive context\\. Use `getHeaders` or implement ClientHeadersFactory\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-reactive/rest-client/runtime/src/main/java/io/quarkus/rest/client/reactive/ReactiveClientHeadersFactory.java","lineNumber":31,"sourceCode":"\n    /**\n     * Updates the HTTP headers to send to the remote service. Note that providers\n     * on the outbound processing chain could further update the headers.\n     *\n     * @param incomingHeaders the map of headers from the inbound JAX-RS request. This will be an empty map if the\n     *        associated client interface is not part of a JAX-RS request.\n     * @param clientOutgoingHeaders the read-only map of header parameters specified on the client interface.\n     * @return a Uni with a map of HTTP headers to merge with the clientOutgoingHeaders to be sent to the remote service.\n     *\n     * @see ClientHeadersFactory#update(MultivaluedMap, MultivaluedMap)\n     */\n    public abstract Uni<MultivaluedMap<String, String>> getHeaders(MultivaluedMap<String, String> incomingHeaders,\n            MultivaluedMap<String, String> clientOutgoingHeaders);\n\n    @Override\n    public final MultivaluedMap<String, String> update(MultivaluedMap<String, String> incomingHeaders,\n            MultivaluedMap<String, String> clientOutgoingHeaders) {\n        throw new RuntimeException(\n                \"Can't call `update` method in a Reactive context. Use `getHeaders` or implement ClientHeadersFactory.\");\n    }\n}\n","sourceCodeStart":13,"sourceCodeEnd":35,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-reactive/rest-client/runtime/src/main/java/io/quarkus/rest/client/reactive/ReactiveClientHeadersFactory.java#L13-L35","documentation":"`ReactiveClientHeadersFactory` implements the blocking `ClientHeadersFactory.update` API but is designed for reactive usage via `getHeaders` returning a Uni. Calling `update` (which the framework does only if the factory is misused as a blocking factory) always throws, directing the developer to override `getHeaders` instead.","triggerScenarios":"Implementing a class extending ReactiveClientHeadersFactory but having it registered where the synchronous ClientHeadersFactory.update path is invoked, or calling update() directly in code/tests.","commonSituations":"Switching an existing ClientHeadersFactory to extend ReactiveClientHeadersFactory without realizing the entry point changed; invoking update() in a unit test.","solutions":["Override `getHeaders(MultivaluedMap, MultivaluedMap)` and put the header logic there returning `Uni.createFrom().item(...)`","Ensure the factory is registered as a reactive headers factory (e.g. via @RegisterClientHeadersFactory pointing at the reactive type)","If blocking logic is needed, extend plain ClientHeadersFactory instead and implement update()"],"exampleFix":"// before\npublic class MyFactory extends ReactiveClientHeadersFactory {\n    public MultivaluedMap<String,String> update(...) { ... }\n}\n// after\npublic class MyFactory extends ReactiveClientHeadersFactory {\n    @Override\n    public Uni<MultivaluedMap<String,String>> getHeaders(MultivaluedMap<String,String> in, MultivaluedMap<String,String> out) {\n        in.add(\"Authorization\", \"Bearer x\");\n        return Uni.createFrom().item(in);\n    }\n}","handlingStrategy":"try-catch","validationCode":"// Ensure subclasses override getHeaders, not update\nfor (Class<?> c : List.of(MyHeadersFactory.class)) {\n  if (ReactiveClientHeadersFactory.class.isAssignableFrom(c)\n      && !Arrays.stream(c.getDeclaredMethods())\n          .anyMatch(m -> m.getName().equals(\"getHeaders\") && !m.isSynthetic())) {\n    throw new IllegalStateException(c + \" must override getHeaders\");\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n    factory.update(incoming, outgoing);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Use `getHeaders`\")) {\n        throw new AssertionError(\"Wrong factory type: use ReactiveClientHeadersFactory.getHeaders\", e);\n    }\n    throw e;\n}","preventionTips":["Always override getHeaders when extending ReactiveClientHeadersFactory","Never call update() directly on reactive factories, including in tests","Use plain ClientHeadersFactory if synchronous behavior is required"],"tags":["rest-client","reactive","headers-factory","misuse"],"backgroundTag":"blocking-api-in-reactive-context","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"}