{"record":{"id":"226fd738daed9c78","repo":"projectdiscovery/nuclei","slug":"w-invalid-tds-packet-length-d","errorCode":null,"errorMessage":"%w: invalid TDS packet length %d","messagePattern":"%w: invalid TDS packet length (.+?)","errorType":"exception","errorClass":"errNotMssql","httpStatus":null,"severity":"warning","filePath":"pkg/js/libs/mssql/fingerprint.go","lineNumber":137,"sourceCode":"\t\treturn info, err\n\t}\n\tdefer func() {\n\t\t_ = conn.Close()\n\t}()\n\n\t_ = conn.SetDeadline(time.Now().Add(mssqlFingerprintTimeout))\n\tif _, err := conn.Write(preLoginRequest); err != nil {\n\t\treturn info, err\n\t}\n\n\t// Read TDS header first, then remaining payload by Length field.\n\theader := make([]byte, 8)\n\tif _, err := io.ReadFull(conn, header); err != nil {\n\t\treturn info, err\n\t}\n\tpacketLen := int(binary.BigEndian.Uint16(header[2:4]))\n\tif packetLen < 8 {\n\t\treturn info, fmt.Errorf(\"%w: invalid TDS packet length %d\", errNotMssql, packetLen)\n\t}\n\tbody := make([]byte, packetLen-8)\n\tif packetLen > 8 {\n\t\tif _, err := io.ReadFull(conn, body); err != nil {\n\t\t\treturn info, err\n\t\t}\n\t}\n\tresponse := append(header, body...)\n\n\tparsed, err := parsePreloginResponse(response)\n\tif err != nil {\n\t\treturn info, fmt.Errorf(\"%w: %v\", errNotMssql, err)\n\t}\n\tinfo.Version = parsed.Version\n\tinfo.MajorVersion = parsed.MajorVersion\n\tinfo.MinorVersion = parsed.MinorVersion\n\tinfo.BuildNumber = parsed.BuildNumber\n\tinfo.Encryption = parsed.Encryption","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/mssql/fingerprint.go#L119-L155","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst info = mssql.FingerprintMssql(host, port); // throws/wraps 'not a mssql service'\n\n// after\nconst isMssql = mssql.IsMssql(host, port); // returns false, no error\nif (isMssql) { const info = mssql.FingerprintMssql(host, port); }","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const info = mssql.FingerprintMssql(host, port);\n} catch (e) {\n  if (String(e).includes('not a mssql service')) {\n    // expected outcome for non-MSSQL services: skip target\n    return;\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["mssql","protocol","tds","fingerprinting","service-detection"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}