jackc/pgx · error
secret key too long
Error message
secret key too long
What it means
Returned by CancelRequest.Encode when SecretKey is longer than 256 bytes. The wire format reserves a single byte for nothing and the server caps the secret key at 256 bytes, so the library refuses to emit a message the server would reject or misparse. This is a caller-side construction error, not a network problem.
Source
Thrown at pgproto3/cancel_request.go:45
return errors.New("cancel request too long")
}
requestCode := binary.BigEndian.Uint32(src)
if requestCode != cancelRequestCode {
return errors.New("bad cancel request code")
}
dst.ProcessID = binary.BigEndian.Uint32(src[4:])
dst.SecretKey = make([]byte, len(src)-8)
copy(dst.SecretKey, src[8:])
return nil
}
// Encode encodes src into dst. dst will include the 4 byte message length.
func (src *CancelRequest) Encode(dst []byte) ([]byte, error) {
if len(src.SecretKey) > 256 {
return nil, errors.New("secret key too long")
}
msgLen := int32(12 + len(src.SecretKey))
dst = pgio.AppendInt32(dst, msgLen)
dst = pgio.AppendInt32(dst, cancelRequestCode)
dst = pgio.AppendUint32(dst, src.ProcessID)
dst = append(dst, src.SecretKey...)
return dst, nil
}
// MarshalJSON implements encoding/json.Marshaler.
func (src CancelRequest) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Type string
ProcessID uint32
SecretKey string
}{
Type: "CancelRequest",
ProcessID: src.ProcessID,View on GitHub (pinned to ec1a0befd2)
Solutions
- Set SecretKey to the 4-byte secret key from the server's BackendKeyData message (the SecretKey field on pgproto3.BackendKeyData), nothing larger.
- Validate before encoding: `if len(req.SecretKey) > 256 { return ... }` (or, more correctly, assert it is 4 bytes).
- Double-check you did not assign ProcessID or a PID slice into SecretKey by mistake.
- If you need a larger cancel token, that is not supported by the PostgreSQL wire protocol — redesign the caller.
Example fix
// before
req := &pgproto3.CancelRequest{
ProcessID: backendKey.ProcessID,
SecretKey: fullBackendKeyBytes, // 8 bytes, wrong
}
_, err := req.Encode(nil)
// after
req := &pgproto3.CancelRequest{
ProcessID: backendKey.ProcessID,
SecretKey: mustSecretKey(backendKey.SecretKey), // exactly 4 bytes
}
_, err := req.Encode(nil) Defensive patterns
Strategy: validation
Validate before calling
func validateCancelRequestEncode(req *pgproto3.CancelRequest) error {
if len(req.SecretKey) > 256 {
return fmt.Errorf("secret key too long: %d bytes (max 256)", len(req.SecretKey))
}
return nil
}
// also assert the realistic 4-byte key from BackendKeyData:
// req.SecretKey must come from backendKeyData.SecretKey (4 bytes) Type guard
null
Try / catch
null
Prevention
- Always source SecretKey from the server's BackendKeyData.SecretKey (a 4-byte uint32), not an arbitrary token.
- Validate struct fields before Encode rather than relying on the encoder to reject them.
- Unit-test the encode path with boundary-length secret keys (0, 4, 255, 256, 257).
When it happens
Trigger: Calling `(*CancelRequest).Encode(dst)` on a struct where `len(SecretKey) > 256`. The real PostgreSQL secret key is exactly 4 bytes (a uint32), so any large slice indicates a caller bug.
Common situations: A caller copies the entire BackendKeyData or a full process credential blob into SecretKey instead of the 4-byte secret key returned by the server in the BackendKeyData message. Also seen in test code that stuffs an arbitrary token into the field.
Related errors
- cancel request too short
- cancel request too long
- too many column format codes
- too many column format codes
- too many column format codes
AI-assisted analysis of jackc/pgx@ec1a0befd2 (2026-08-04).
Data as JSON: /data/errors/b235112579240332.json.
Report an issue: GitHub.