shadow1ng/fscan · error
mssql: packet type changed in message
Error message
mssql: packet type changed in message
What it means
mssqlReadMessage assembles a TDS message from one or more packets; every packet of a message must carry the same packet type byte. If a continuation packet's type differs from the type recorded for the first packet, the stream violates the TDS framing rules and reading aborts with this error.
Source
Thrown at plugins/services/mssql_raw.go:433
if _, err := w.Write(header); err != nil {
return err
}
_, err := w.Write(payload)
return err
}
func mssqlReadMessage(r io.Reader) (byte, []byte, error) {
var packetType byte
var payload []byte
for {
header := make([]byte, 8)
if _, err := io.ReadFull(r, header); err != nil {
return 0, nil, err
}
if packetType == 0 {
packetType = header[0]
} else if packetType != header[0] {
return 0, nil, fmt.Errorf("mssql: packet type changed in message")
}
size := int(binary.BigEndian.Uint16(header[2:4]))
if size < 8 {
return 0, nil, fmt.Errorf("mssql: invalid packet size")
}
chunk := make([]byte, size-8)
if _, err := io.ReadFull(r, chunk); err != nil {
return 0, nil, err
}
if len(payload)+len(chunk) > maxTDSMessageSize {
return 0, nil, fmt.Errorf("mssql: message too large")
}
payload = append(payload, chunk...)
if header[1]&tdsStatusEOM != 0 {
return packetType, payload, nil
}
}
}View on GitHub (pinned to 95cc12e753)
Solutions
- Confirm the peer is a real SQL Server speaking TDS on the expected port.
- Discard the connection and restart the handshake — the stream is desynchronized once framing is violated.
- Check for middleboxes/proxies multiplexing the TCP stream and connect directly.
- If parsing crafted input, note the parser correctly rejects it; treat it as untrusted and stop.
Defensive patterns
Strategy: try-catch
Try / catch
pktType, payload, err := mssqlReadMessage(conn)
if err != nil {
if strings.Contains(err.Error(), "packet type changed") {
conn.Close() // stream desynchronized; restart handshake or drop target
}
} Prevention
- Connect only to confirmed SQL Server TDS endpoints.
- Avoid proxies that multiplex or reorder TCP streams.
- Log the offending packet type bytes to identify non-TDS peers.
- Treat framing violations as fatal for the connection.
When it happens
Trigger: Reading a prelogin or login response where a multi-packet message (status EOM bit not set on the first packet) arrives whose subsequent packet header contains a different type byte than the first — a corrupted, interleaved, or non-TDS stream.
Common situations: Port serving a different protocol that happens to emit 8-byte-aligned garbage; a proxy interleaving responses from two connections; an intentional malicious server mixing packet types to break parsers.
Related errors
- mssql: invalid us varchar size
- mssql: invalid packet size
- mssql: login acknowledgement not received
- mssql: invalid prelogin response packet type %d
- mssql: empty prelogin response
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/68164c9d24f09c76.
Report an issue: GitHub.