{"record":{"id":"5d6d8f4193ad0b95","repo":"apache/shardingsphere","slug":"close-type-must-be-s-or-p-got-c","errorCode":null,"errorMessage":"Close type must be 'S' or 'P'. Got '%c'.","messagePattern":"Close type must be 'S' or 'P'\\. Got '%c'\\.","errorType":"exception","errorClass":"PostgreSQLProtocolException","httpStatus":null,"severity":"error","filePath":"database/protocol/dialect/postgresql/src/main/java/org/apache/shardingsphere/database/protocol/postgresql/packet/command/query/extended/close/PostgreSQLComClosePacket.java","lineNumber":75,"sourceCode":"        \n        PORTAL('P');\n        \n        private final char value;\n        \n        /**\n         * Value of type.\n         *\n         * @param type type char\n         * @return type\n         * @throws PostgreSQLProtocolException PostgreSQL protocol exception\n         */\n        public static Type valueOf(final char type) {\n            for (Type each : values()) {\n                if (type == each.value) {\n                    return each;\n                }\n            }\n            throw new PostgreSQLProtocolException(\"Close type must be 'S' or 'P'. Got '%c'.\", type);\n        }\n    }\n}\n","sourceCodeStart":57,"sourceCodeEnd":79,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/database/protocol/dialect/postgresql/src/main/java/org/apache/shardingsphere/database/protocol/postgresql/packet/command/query/extended/close/PostgreSQLComClosePacket.java#L57-L79","documentation":"PostgreSQLComClosePacket.Type.valueOf(char) maps the single byte after the Close message tag to either 'S' (prepared statement) or 'P' (portal). Any other byte throws PostgreSQLProtocolException 'Close type must be 'S' or 'P'. Got '%c'.', meaning the incoming Close message is malformed per the PostgreSQL frontend/backend protocol.","triggerScenarios":"A client sends a Close message (tag 'C') whose type byte is neither 'S' nor 'P' — from a buggy driver, a protocol-level proxy mangling bytes, a truncated TCP stream, or fuzzed input.","commonSituations":"Custom wire-protocol clients, broken middleware between client and proxy, partial writes producing byte misalignment, or driver/protocol version mismatches.","solutions":["Capture the raw bytes of the Close message and verify the client implementation sends exactly 'S' or 'P' after the tag","If using a custom client, check message construction order against the PostgreSQL protocol spec (Close is: tag, type byte, name, NUL)","Rule out middleboxes/proxies that rewrite the stream; test the client directly against the proxy","Report a driver bug if a mainstream driver emits the invalid byte"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (typeChar != 'S' && typeChar != 'P') { throw new IllegalArgumentException(\"Close type byte must be 'S' or 'P'\"); }","typeGuard":null,"tryCatchPattern":"catch (PostgreSQLProtocolException e) { /* terminate connection: stream is untrusted/desynced */ }","preventionTips":["Test custom wire clients against vanilla PostgreSQL first","Verify Close message byte order per protocol spec","Watch for middleware that rewrites the byte stream"],"tags":["postgresql","protocol","close-packet","malformed-input"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}