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.Encryption

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Treat this error as 'not MSSQL' and continue scanning — use mssql.IsMssql(host, port) instead if you want a clean boolean
  2. Verify the port really is the SQL Server TCP port (default 1433 or the named-instance port from SQL Browser)
  3. 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

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


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/226fd738daed9c78. Report an issue: GitHub.