{"record":{"id":"b5e831fee01c9893","repo":"quarkusio/quarkus","slug":"was-already-open","errorCode":null,"errorMessage":"Was already open","messagePattern":"Was already open","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"error","filePath":"independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/SseEventSourceImpl.java","lineNumber":152,"sourceCode":"                    delayMs = Math.min(serverDelayMs, Math.max(defaultDelayMs, 300_000));\n                }\n            } catch (NumberFormatException e) {\n                // unparseable — use default\n            }\n        }\n        Vertx vertx = webTarget.getRestClient().getVertx();\n        if (timerId != -1) {\n            vertx.cancelTimer(timerId);\n        }\n        timerId = vertx.setTimer(delayMs, this);\n    }\n\n    /**\n     * Allows the HTTP client to register for SSE after it has made the request\n     */\n    synchronized void registerAfterRequest(HttpClientResponse vertxClientResponse) {\n        if (isOpen)\n            throw new IllegalStateException(\"Was already open\");\n        isOpen = true;\n        registerOnClient(vertxClientResponse);\n    }\n\n    private void registerOnClient(HttpClientResponse vertxClientResponse) {\n        // make sure we get exceptions on the response, like close events, otherwise they\n        // will be logged as errors by vertx\n        vertxClientResponse.exceptionHandler(t -> {\n            if (t == ConnectionBase.CLOSED_EXCEPTION) {\n                // we can ignore this one since we registered a closeHandler\n            } else {\n                receiveThrowable(t);\n            }\n        });\n        // since we registered our exception handler, let's remove the request exception handler\n        // that is set in ClientSendRequestHandler\n        vertxClientResponse.request().exceptionHandler(null);\n        connection = vertxClientResponse.request().connection();","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/SseEventSourceImpl.java#L134-L170","documentation":"SseEventSourceImpl.registerAfterRequest throws this IllegalStateException if the source's isOpen flag is already true when the HTTP client tries to register the SSE listener on the response. Each SSE event source may only open one stream; opening it twice is a lifecycle misuse.","triggerScenarios":"Calling open()/register() twice on the same SseEventSource instance, or re-using an already-open source for a new request; manual calls to registerAfterRequest after the source is open.","commonSituations":"Retrying a failed SSE request by calling open() again on the same source instance instead of creating a new one; caching SseEventSource objects and sharing them across requests; resuming a stream after connection drop without recreating the source.","solutions":["Create a new SseEventSource (target.sse()) for each connection/open call","Close the existing source before attempting to register/open again","Guard calls with source.isOpen() before opening"],"exampleFix":"// before\nSseEventSource source = sseSource; // reused\nsource.open(); // second call -> Was already open\n// after\nSseEventSource source = webTarget.sse(); // fresh instance\nsource.open();","handlingStrategy":"try-catch","validationCode":"if (source.isOpen()) {\n    source = webTarget.sse(); // replace with a fresh source\n}\nsource.open();","typeGuard":"SseEventSource ensureClosed(SseEventSource src) {\n    if (src != null && src.isOpen()) src.close();\n    return src;\n}","tryCatchPattern":"try {\n    source.open();\n} catch (IllegalStateException e) {\n    if (\"Was already open\".equals(e.getMessage())) {\n        source.close();\n        source = webTarget.sse();\n        source.open();\n    } else throw e;\n}","preventionTips":["Create a new SseEventSource per connection; never reopen an open source","Close sources in a finally block or on cancellation","Guard with source.isOpen() before open()"],"tags":["sse","rest-client-reactive","illegal-state","lifecycle"],"backgroundTag":"resource-already-open","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"}