{"id":"0fcd94a49cab4100","repo":"jackc/pgx","slug":"bad-gss-encoding-request-code","errorCode":null,"errorMessage":"bad gss encoding request code","messagePattern":"bad gss encoding request code","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pgproto3/gss_enc_request.go","lineNumber":26,"sourceCode":"\t\"github.com/jackc/pgx/v5/internal/pgio\"\n)\n\nconst gssEncReqNumber = 80877104\n\ntype GSSEncRequest struct{}\n\n// Frontend identifies this message as sendable by a PostgreSQL frontend.\nfunc (*GSSEncRequest) Frontend() {}\n\nfunc (dst *GSSEncRequest) Decode(src []byte) error {\n\tif len(src) < 4 {\n\t\treturn errors.New(\"gss encoding request too short\")\n\t}\n\n\trequestCode := binary.BigEndian.Uint32(src)\n\n\tif requestCode != gssEncReqNumber {\n\t\treturn errors.New(\"bad gss encoding request code\")\n\t}\n\n\treturn nil\n}\n\n// Encode encodes src into dst. dst will include the 4 byte message length.\nfunc (src *GSSEncRequest) Encode(dst []byte) ([]byte, error) {\n\tdst = pgio.AppendInt32(dst, 8)\n\tdst = pgio.AppendInt32(dst, gssEncReqNumber)\n\treturn dst, nil\n}\n\n// MarshalJSON implements encoding/json.Marshaler.\nfunc (src GSSEncRequest) MarshalJSON() ([]byte, error) {\n\treturn json.Marshal(struct {\n\t\tType            string\n\t\tProtocolVersion uint32\n\t\tParameters      map[string]string","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/jackc/pgx/blob/ec1a0befd22592cffffdeeb0a50311b506372f4c/pgproto3/gss_enc_request.go#L8-L44","documentation":"Returned by GSSEncRequest.Decode when the first 4 bytes do not equal the GSS-encryption request magic number 80877104. That magic (0x04D21630) is how PostgreSQL distinguishes a GSS request from an SSL request (80877103), a cancel request (80877102), or a normal startup message on a fresh connection. A mismatch means the bytes are not a GSS request.","triggerScenarios":"`(*GSSEncRequest).Decode(src)` where `binary.BigEndian.Uint32(src) != 80877104`. Happens when an SSL request, cancel request, or startup packet is mistakenly fed to the GSS decoder, or when the bytes are corrupted.","commonSituations":"A proxy or test server reads the first int32 from a fresh connection and dispatches to GSSEncRequest.Decode without first switching on the code. Also caused by endianness mistakes or in-transit corruption.","solutions":["Switch on the first uint32 before decoding: 80877103 → SSL, 80877104 → GSS, 80877102 → cancel, else → startup.","Verify bytes are read in big-endian (network) order.","Confirm the sender is actually issuing a GSS-encryption request (client sets gssencmode=require/prefer), not SSL or startup.","If proxying, track connection state so only a GSS code routes to the GSS decoder."],"exampleFix":"// before\nvar gss pgproto3.GSSEncRequest\nerr := gss.Decode(body) // body was an SSL request (80877103)\n\n// after\ncode := binary.BigEndian.Uint32(body)\nswitch code {\ncase 80877103: // SSL request\ncase 80877104: // GSS request\n    var gss pgproto3.GSSEncRequest\n    err := gss.Decode(body)\ncase 80877102: // cancel request\ndefault: // startup message\n}","handlingStrategy":"validation","validationCode":"func dispatchGSSCode(body []byte) error {\n\tif len(body) < 4 {\n\t\treturn errors.New(\"frame too short for gss code\")\n\t}\n\tswitch binary.BigEndian.Uint32(body) {\n\tcase 80877104: // GSS\n\t\tvar g pgproto3.GSSEncRequest\n\t\treturn g.Decode(body)\n\tcase 80877103: // SSL\n\tcase 80877102: // cancel\n\tdefault: // startup\n\t}\n\treturn nil\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Switch on the first uint32 of a fresh connection before picking a decoder.","Read the magic in big-endian order.","Track per-connection state in a proxy so GSS/SSL/cancel/startup route to the right decoder."],"tags":["pgproto3","protocol","decoding","gss","wire-protocol","authentication"],"analyzedSha":"ec1a0befd22592cffffdeeb0a50311b506372f4c","analyzedAt":"2026-08-04T22:52:11.263Z","schemaVersion":2}