{"record":{"id":"c19e23029f026a80","repo":"jd-opensource/joyagent-jdgenie","slug":"sse-listener-failed","errorCode":null,"errorMessage":"sse listener failed ","messagePattern":"sse listener failed ","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"genie-backend/src/main/java/com/jd/genie/service/Nl2SqlService.java","lineNumber":66,"sourceCode":"        request.setStream(false);\n        String jsonResult = OkHttpUtil.postJsonBody(dataAgentConfig.getAgentUrl() + NL2SQL_URL, null, JSONObject.toJSONString(request));\n        log.info(\"{},{} nl2sql result without sse:{}\", request.getTraceId(), request.getRequestId(), jsonResult);\n        NL2SQLResult nl2SQLResult = JSONObject.parseObject(jsonResult, NL2SQLResult.class);\n        if (err.get() != null) {\n            throw new RuntimeException(\"sse nl2sql failed:\" + err.get().getMessage());\n        }\n        return nl2sqlQueryData(request, nl2SQLResult);\n    }\n\n    public List<ChatQueryData> runNL2SQLSse(NL2SQLReq request, SseEmitter emitter) throws Exception {\n        AtomicReference<Throwable> err = new AtomicReference<>();\n        Nl2SqlSseListener sqlSseListener = new Nl2SqlSseListener(emitter, request.getRequestId(), request.getTraceId());\n        OkHttpUtil.requestSse(dataAgentConfig.getAgentUrl() + NL2SQL_URL, null, JSONObject.toJSONString(request), sqlSseListener);\n        sqlSseListener.getCountDownLatch().await();\n        int eventCount = sqlSseListener.getEventCount();\n        log.info(\"{} sse event count:{}\", request.getRequestId(), eventCount);\n        if (!sqlSseListener.isSuccess()) {\n            throw new RuntimeException(\"sse listener failed \" + sqlSseListener.getErrorMessage());\n        }\n        NL2SQLResult nl2SQLResult = sqlSseListener.getNl2SQLResult();\n        if (err.get() != null) {\n            throw new RuntimeException(\"sse nl2sql failed:\" + err.get().getMessage());\n        }\n        return nl2sqlQueryData(request, nl2SQLResult);\n    }\n\n\n    public String replaceFirstMatchedOrThrow(String input, List<String> codeList) {\n        if (input == null || codeList == null || codeList.isEmpty()) {\n            throw new IllegalArgumentException(\"nl2sql返回对象为空\");\n        }\n\n        List<Pattern> patterns = codeList.stream()\n                .distinct()\n                .map(code -> Pattern.compile(\"(?i)(?<!`)\\\\b\" + Pattern.quote(code) + \"\\\\b(?!`)\"))\n                .toList();","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/jd-opensource/joyagent-jdgenie/blob/2417e0b8b636d941ad5fb14c59b20dddfef5375d/genie-backend/src/main/java/com/jd/genie/service/Nl2SqlService.java#L48-L84","documentation":"runNL2SQLSse streams the NL2SQL request over SSE and waits on the listener's CountDownLatch. If the Nl2SqlSseListener reports failure (isSuccess()==false), the accumulated errorMessage is wrapped in this RuntimeException. It signals the SSE stream itself failed or completed without a successful result event.","triggerScenarios":"After await() returns, sqlSseListener.isSuccess() is false — e.g. the SSE connection failed, an error event was received, or the stream closed before a final NL2SQLResult arrived.","commonSituations":"Agent crash mid-stream; proxy/gateway cutting long-lived SSE connections; requestId/traceId mismatch handling; agent returning an error event for bad SQL or schema prompts.","solutions":["Inspect the appended sqlSseListener.getErrorMessage() for the stream-level cause","Check agent logs for the requestId included in the request","Confirm no LB/proxy idle timeout is terminating SSE connections; increase timeouts","Retry the request; treat non-success terminal events as retryable if transient"],"exampleFix":"// before\nthrow new RuntimeException(\"sse listener failed \" + sqlSseListener.getErrorMessage());\n// after\nthrow new RuntimeException(\"sse listener failed: \" + sqlSseListener.getErrorMessage() + \", requestId=\" + request.getRequestId());","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    return nl2SqlService.runNL2SQLSse(request, emitter);\n} catch (RuntimeException e) {\n    if (e.getMessage().startsWith(\"sse listener failed\")) {\n        log.error(\"sse stream failed: {}\", e.getMessage());\n        // retry once or notify client of upstream failure\n    }\n    throw e;\n}","preventionTips":["Configure proxy/LB SSE idle timeouts generously","Monitor agent stability for long streams","Implement one bounded retry for transient SSE failures"],"tags":["sse","network","nl2sql","stream"],"backgroundTag":"upstream-api-error","analyzedSha":"2417e0b8b636d941ad5fb14c59b20dddfef5375d","analyzedAt":"2026-09-08T11:28:19.414Z","contentChangedAt":"2026-09-08T11:28:19.414Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}