projectdiscovery/nuclei · warning · errNotMssql
%w: %v
Error message
%w: %v
What it means
Returned by mssql.FingerprintMssql when parsePreloginResponse rejects the assembled packet, wrapping the specific parse failure (bad type byte, bad status byte, length mismatch, malformed option tokens) with the errNotMssql sentinel. Semantically identical to the raw length check: the service answered but the reply is not a valid MSSQL pre-login response, so the target is presumed not MSSQL.
Source
Thrown at pkg/js/libs/mssql/fingerprint.go:149
header := make([]byte, 8)
if _, err := io.ReadFull(conn, header); err != nil {
return info, err
}
packetLen := int(binary.BigEndian.Uint16(header[2:4]))
if packetLen < 8 {
return info, fmt.Errorf("%w: invalid TDS packet length %d", errNotMssql, packetLen)
}
body := make([]byte, packetLen-8)
if packetLen > 8 {
if _, err := io.ReadFull(conn, body); err != nil {
return info, err
}
}
response := append(header, body...)
parsed, err := parsePreloginResponse(response)
if err != nil {
return info, fmt.Errorf("%w: %v", errNotMssql, err)
}
info.Version = parsed.Version
info.MajorVersion = parsed.MajorVersion
info.MinorVersion = parsed.MinorVersion
info.BuildNumber = parsed.BuildNumber
info.Encryption = parsed.Encryption
info.EncryptionMode = parsed.EncryptionMode
info.Mars = parsed.Mars
info.InstanceMatches = parsed.InstanceMatches
info.TLS = parsed.Encryption == encryptOn || parsed.Encryption == encryptReq
info.Raw = hex.EncodeToString(response)
if ip := net.ParseIP(host); ip != nil {
info.IP = ip.String()
}
return info, nil
}
type preloginData struct {View on GitHub (pinned to 265b3a3dec)
Solutions
- Handle it as 'not MSSQL' and move on, or switch to mssql.IsMssql for a boolean result
- Confirm you are hitting the real SQL TCP port, not a TLS frontend (try the TLS-port variant or check for a 0x16 first byte)
- Log the raw hex (info.Raw on success paths) while debugging to see what the service actually sent
Defensive patterns
Strategy: fallback
Try / catch
try {
const info = mssql.FingerprintMssql(host, port);
} catch (e) {
if (String(e).includes('not a mssql service')) return; // classify as non-MSSQL
throw e; // real network errors still propagate
} Prevention
- Filter on the errNotMssql message to separate 'not MSSQL' from transport errors
- Prefer IsMssql for pure detection flows
- When MSSQL is expected, check for a TLS-first listener (0x16 first byte) before probing
When it happens
Trigger: The reply's first bytes are a TLS ServerHello / alert (byte 0x16/0x15) instead of a TDS tabular-result packet; an HTTP error page on the port; a half-broken proxy answer that passes the >=8 length check but fails deeper structure validation.
Common situations: Probing ports behind load balancers or TLS-terminating proxies; servers that force encryption from the first byte; any non-MSSQL service that happens to send 8+ bytes whose length field looks plausible.
Related errors
- %w: invalid TDS packet length %d
- unexpected TDS type 0x%02x
- unexpected TDS status 0x%02x
- not a mssql service
- response too short for TDS header
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/62680a68d0605033.
Report an issue: GitHub.