{"record":{"id":"67b43e2e1ee01675","repo":"MyCATApache/Mycat-Server","slug":"the-select-proess-err-the-selectresponse-is-empty","errorCode":null,"errorMessage":"the select proess err ,the SelectResponse is empty","messagePattern":"the select proess err ,the SelectResponse is empty","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/backend/postgresql/PostgreSQLBackendConnectionHandler.java","lineNumber":289,"sourceCode":"\n\t\t// end row\n\t\tbufferArray = MycatServer.getInstance().getBufferPool().allocateArray();\n\t\teofPckg = new EOFPacket();\n\t\teofPckg.packetId = ++packetId;\n\t\teofPckg.write(bufferArray);\n\t\teof = bufferArray.writeToByteArrayAndRecycle();\n\t\tif (con.getResponseHandler() != null) {\n\t\t\tcon.getResponseHandler().rowEofResponse(eof, con);\n\t\t} else {\n\t\t\tLOGGER.error(\"响应句柄为空\");\n\t\t}\n\t}\n\n\tprivate void doProcessCommandComplete(PostgreSQLBackendConnection con,\n\t\t\tCommandComplete commandComplete, SelectResponse response) {\n\t\tif (commandComplete.isSelectComplete()) {\n\t\t\tif (response == null) {\n\t\t\t\tthrow new RuntimeException(\n\t\t\t\t\t\t\"the select proess err ,the SelectResponse is empty\");\n\t\t\t}\n\t\t\tdoProcessBusinessQuery(con, response, commandComplete);\n\t\t} else {\n\t\t\tOkPacket okPck = new OkPacket();\n\t\t\t\n\t\t\tokPck.affectedRows =commandComplete.getAffectedRows();\n\t\t\tokPck.insertId =commandComplete.getInsertId();\n\t\t\tokPck.packetId = ++packetId;\n\t\t\tokPck.message = commandComplete.getCommandResponse().getBytes();\n\t\t\tcon.getResponseHandler().okResponse(okPck.writeToBytes(), con);\n\t\t}\n\t}\n\n\tprivate void doProcessCopyInResponse(PostgreSQLBackendConnection con,\n\t\t\tCopyInResponse packet) {\n\t\t// TODO(复制数据暂时不需要)\n\t}","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/backend/postgresql/PostgreSQLBackendConnectionHandler.java#L271-L307","documentation":"PostgreSQLBackendConnectionHandler.doProcessCommandComplete() handles a CommandComplete from the PG backend. When the command was a SELECT (isSelectComplete()==true) but the handler's SelectResponse accumulator is null — no RowDescription started a response object — it throws this RuntimeException instead of forwarding results.","triggerScenarios":"A CommandComplete for a SELECT arrives without a preceding RowDescription packet having created a SelectResponse, e.g. protocol desync, packets dropped/processed out of order, or a query the handler did not register as a select.","commonSituations":"Protocol desync after a prior PG error/ErrorResponse that skipped RowDescription; complex queries (e.g. via views/functions) whose packet flow the handler mislabels; MyCat PG backend bugs on extended-protocol or COPY-like flows.","solutions":["Check the PG server log and MyCat log for a preceding ErrorResponse that broke the RowDescription->DataRow->CommandComplete sequence; fix the underlying query error first","Upgrade/patch MyCat's PG handler to create a SelectResponse defensively when isSelectComplete() is true but response is null","Close and recycle the affected backend connection — its protocol state is desynced","Simplify/adjust the query that triggers the mislabeled packet flow (e.g. avoid the specific function/COPY path)"],"exampleFix":"// before\nif (response == null) { throw new RuntimeException(\"the select proess err ,the SelectResponse is empty\"); }\n// after\nif (response == null) { LOGGER.error(\"select complete without SelectResponse, con=\" + con); con.close(\"select response missing\"); return; }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"if (response == null) { /* skip/repair before processing */ }\n// in handler code:\nif (commandComplete.isSelectComplete() && response != null) { doProcessBusinessQuery(con, response, commandComplete); }","tryCatchPattern":"try { session.execute(select); } catch (RuntimeException e) { if (e.getMessage() != null && e.getMessage().contains(\"SelectResponse is empty\")) { pool.invalidate(conn); /* retry on fresh connection */ } else { throw e; } }","preventionTips":["Fix underlying PG errors that desync RowDescription/CommandComplete flow","Recycle backend connections after protocol errors","Upgrade MyCat PG handler patches"],"tags":["postgresql","protocol","select","desync"],"backgroundTag":"internal-invariant-violation","analyzedSha":"65f8d8beb752f935752f2a0eec0ab017facab9ef","analyzedAt":"2026-09-11T00:12:21.696Z","contentChangedAt":"2026-09-11T00:12:21.696Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}