quarkusio/quarkus · error · RuntimeException

Can't call `update` method in a Reactive context. Use `getHe

Error message

Can't call `update` method in a Reactive context. Use `getHeaders` or implement ClientHeadersFactory.

What it means

`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.

Source

Thrown at extensions/resteasy-reactive/rest-client/runtime/src/main/java/io/quarkus/rest/client/reactive/ReactiveClientHeadersFactory.java:31

    /**
     * Updates the HTTP headers to send to the remote service. Note that providers
     * on the outbound processing chain could further update the headers.
     *
     * @param incomingHeaders the map of headers from the inbound JAX-RS request. This will be an empty map if the
     *        associated client interface is not part of a JAX-RS request.
     * @param clientOutgoingHeaders the read-only map of header parameters specified on the client interface.
     * @return a Uni with a map of HTTP headers to merge with the clientOutgoingHeaders to be sent to the remote service.
     *
     * @see ClientHeadersFactory#update(MultivaluedMap, MultivaluedMap)
     */
    public abstract Uni<MultivaluedMap<String, String>> getHeaders(MultivaluedMap<String, String> incomingHeaders,
            MultivaluedMap<String, String> clientOutgoingHeaders);

    @Override
    public final MultivaluedMap<String, String> update(MultivaluedMap<String, String> incomingHeaders,
            MultivaluedMap<String, String> clientOutgoingHeaders) {
        throw new RuntimeException(
                "Can't call `update` method in a Reactive context. Use `getHeaders` or implement ClientHeadersFactory.");
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Override `getHeaders(MultivaluedMap, MultivaluedMap)` and put the header logic there returning `Uni.createFrom().item(...)`
  2. Ensure the factory is registered as a reactive headers factory (e.g. via @RegisterClientHeadersFactory pointing at the reactive type)
  3. If blocking logic is needed, extend plain ClientHeadersFactory instead and implement update()

Example fix

// before
public class MyFactory extends ReactiveClientHeadersFactory {
    public MultivaluedMap<String,String> update(...) { ... }
}
// after
public class MyFactory extends ReactiveClientHeadersFactory {
    @Override
    public Uni<MultivaluedMap<String,String>> getHeaders(MultivaluedMap<String,String> in, MultivaluedMap<String,String> out) {
        in.add("Authorization", "Bearer x");
        return Uni.createFrom().item(in);
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure subclasses override getHeaders, not update
for (Class<?> c : List.of(MyHeadersFactory.class)) {
  if (ReactiveClientHeadersFactory.class.isAssignableFrom(c)
      && !Arrays.stream(c.getDeclaredMethods())
          .anyMatch(m -> m.getName().equals("getHeaders") && !m.isSynthetic())) {
    throw new IllegalStateException(c + " must override getHeaders");
  }
}

Try / catch

try {
    factory.update(incoming, outgoing);
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().contains("Use `getHeaders`")) {
        throw new AssertionError("Wrong factory type: use ReactiveClientHeadersFactory.getHeaders", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Implementing a class extending ReactiveClientHeadersFactory but having it registered where the synchronous ClientHeadersFactory.update path is invoked, or calling update() directly in code/tests.

Common situations: Switching an existing ClientHeadersFactory to extend ReactiveClientHeadersFactory without realizing the entry point changed; invoking update() in a unit test.

Related errors


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