shadow1ng/fscan · error

mssql: message too large

Error message

mssql: message too large

What it means

A single TDS message may span many packets, so mssqlReadMessage enforces a maximum accumulated payload size (maxTDSMessageSize) while concatenating chunks. If adding the next chunk would exceed that limit, the read aborts with this error to prevent unbounded memory growth from a hostile or broken peer.

Source

Thrown at plugins/services/mssql_raw.go:444

		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
		}
	}
}

func mssqlUCS2(s string) []byte {
	runes := utf16.Encode([]rune(s))
	out := make([]byte, len(runes)*2)
	for i, r := range runes {
		binary.LittleEndian.PutUint16(out[i*2:], r)
	}
	return out
}

func mssqlDecodeUCS2(data []byte) string {

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Check the peer's EOM-bit handling: a legitimate server terminates every message; non-termination suggests a fake server — blocklist the target.
  2. Keep the limit in place (DoS protection); do not raise maxTDSMessageSize for untrusted hosts.
  3. Reset the connection and retry once in case of transient corruption.
  4. If you control the server side, fix it to set the EOM status bit on the final packet.
Defensive patterns

Strategy: retry

Try / catch

_, payload, err := mssqlReadMessage(conn)
if err != nil {
    if strings.Contains(err.Error(), "message too large") {
        // one clean reconnect; if it recurs, blocklist the target
        conn.Close()
        return retryOnceOrBlocklist(target)
    }
}

Prevention

When it happens

Trigger: A prelogin/login response that keeps sending continuation packets (EOM bit unset) until accumulated payload exceeds maxTDSMessageSize — e.g. a server (or fake server) streaming endless non-terminating packets.

Common situations: Malicious TDS honeypots or fuzz servers never setting the EOM bit; a buggy server sending very large prelogin responses; a parser bug causing EOM detection to miss termination.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/20c53f3f83117ef8. Report an issue: GitHub.