projectdiscovery/nuclei · warning · errNotMssql
%w: invalid TDS packet length %d
Error message
%w: invalid TDS packet length %d
What it means
Returned by mssql.FingerprintMssql when the 8-byte TDS header was read but the big-endian length field at bytes 2-3 is less than 8 (a TDS packet is never shorter than its own header). It wraps the sentinel errNotMssql ('not a mssql service'): the port answered, but the reply is not a well-formed TDS pre-login response. The sibling API IsMssql maps this sentinel to (false, nil) — only FingerprintMssql surfaces it as an error.
Source
Thrown at pkg/js/libs/mssql/fingerprint.go:137
return info, err
}
defer func() {
_ = conn.Close()
}()
_ = conn.SetDeadline(time.Now().Add(mssqlFingerprintTimeout))
if _, err := conn.Write(preLoginRequest); err != nil {
return info, err
}
// Read TDS header first, then remaining payload by Length field.
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.EncryptionView on GitHub (pinned to 265b3a3dec)
Solutions
- Treat this error as 'not MSSQL' and continue scanning — use mssql.IsMssql(host, port) instead if you want a clean boolean
- Verify the port really is the SQL Server TCP port (default 1433 or the named-instance port from SQL Browser)
- Check the raw service first (e.g. TLS handshake byte 0x16) if you expect encryption-forced SQL Server
Example fix
// before
const info = mssql.FingerprintMssql(host, port); // throws/wraps 'not a mssql service'
// after
const isMssql = mssql.IsMssql(host, port); // returns false, no error
if (isMssql) { const info = mssql.FingerprintMssql(host, port); } Defensive patterns
Strategy: fallback
Try / catch
try {
const info = mssql.FingerprintMssql(host, port);
} catch (e) {
if (String(e).includes('not a mssql service')) {
// expected outcome for non-MSSQL services: skip target
return;
}
throw e;
} Prevention
- Use mssql.IsMssql(host, port) when you want (false, nil) instead of an error
- Only fingerprint ports confirmed as the SQL TCP port (1433 or named-instance port)
- Treat 'not a mssql service' as a normal scan result, not a failure
When it happens
Trigger: Fingerprinting an open port that speaks something other than TDS (HTTP, Redis, arbitrary banner) so the first bytes decode to a bogus length < 8; hitting a TCP wrapper/middlebox that returns a short non-TDS greeting.
Common situations: Scanning a /24 on 1433 where some IPs run other services on that port; pointing the probe at the UDP browser port 1434 by mistake; health-check endpoints on reused ports.
Related errors
- %w: %v
- 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/226fd738daed9c78.
Report an issue: GitHub.