quarkusio/quarkus · error · java.lang.IllegalArgumentException

Delay must be > 0: <reconnectDelay>

Error message

Delay must be > 0: <reconnectDelay>

What it means

The SseEventSourceImpl constructor validates reconnectDelay and throws this IllegalArgumentException when it is zero or negative (a null TimeUnit also fails via requireNonNull). It is the constructor-level duplicate of the builder-side check, protecting the SSE parser's reconnect timer.

Source

Thrown at independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/SseEventSourceImpl.java:54

    private final List<Consumer<InboundSseEvent>> consumers = new ArrayList<>();
    private final List<Consumer<Throwable>> errorListeners = new ArrayList<>();
    private final List<Runnable> completionListeners = new ArrayList<>();
    private HttpConnection connection;
    private final SseParser sseParser;
    private long timerId = -1;
    private boolean receivedClientClose;

    public SseEventSourceImpl(WebTargetImpl webTarget, Invocation.Builder invocationBuilder,
            long reconnectDelay, TimeUnit reconnectUnit) {
        this(webTarget, invocationBuilder, reconnectDelay, reconnectUnit, null);
    }

    public SseEventSourceImpl(WebTargetImpl webTarget, Invocation.Builder invocationBuilder,
            long reconnectDelay, TimeUnit reconnectUnit, String defaultContentType) {
        // tests set a null endpoint
        Objects.requireNonNull(reconnectUnit);
        if (reconnectDelay <= 0)
            throw new IllegalArgumentException("Delay must be > 0: " + reconnectDelay);
        this.webTarget = webTarget;
        this.reconnectDelay = reconnectDelay;
        this.reconnectUnit = reconnectUnit;
        this.sseParser = new SseParser(this, defaultContentType);
        this.invocationBuilder = invocationBuilder;
    }

    WebTargetImpl getWebTarget() {
        return webTarget;
    }

    @Override
    public synchronized void register(Consumer<InboundSseEvent> onEvent) {
        consumers.add(onEvent);
    }

    @Override
    public synchronized void register(Consumer<InboundSseEvent> onEvent, Consumer<Throwable> onError) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Pass a positive reconnectDelay (e.g. 500 with TimeUnit.MILLISECONDS)
  2. Set the client config property to a valid duration (e.g. quarkus.rest-client.<key>.sse-reconnect-interval=PT1S)
  3. Clamp or validate the configured value before constructing the source

Example fix

// before
new SseEventSourceImpl(target, builder, 0, TimeUnit.SECONDS, null);
// after
new SseEventSourceImpl(target, builder, 1, TimeUnit.SECONDS, null);
Defensive patterns

Strategy: validation

Validate before calling

Objects.requireNonNull(unit, "reconnectUnit required");
if (reconnectDelay <= 0) {
    throw new IllegalArgumentException("reconnectDelay must be > 0, got: " + reconnectDelay);
}
SseEventSourceImpl source = new SseEventSourceImpl(webTarget, builder, reconnectDelay, unit, contentType);

Type guard

boolean canCreateSseSource(long delay, TimeUnit unit) {
    return unit != null && delay > 0;
}

Try / catch

try {
    source = new SseEventSourceImpl(target, invBuilder, delay, unit, type);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Delay must be > 0")) {
        source = new SseEventSourceImpl(target, invBuilder, 1, TimeUnit.SECONDS, type);
    } else throw e;
}

Prevention

When it happens

Trigger: Constructing SseEventSourceImpl directly (or through a custom builder path) with reconnectDelay <= 0; reading a reconnect delay from configuration where the default is 0.

Common situations: Programmatic construction of SSE sources without the validating builder; config properties like quarkus.rest-client.sse-reconnect-interval set to an invalid zero/negative value; wrong unit conversion producing 0.

Related errors


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