shadow1ng/fscan · error

mssql: truncated error token

Error message

mssql: truncated error token

What it means

mssqlParseErrorToken was asked to read an ERROR token from a raw TDS login-response payload, but fewer than 2 bytes remained at the current offset, so the 2-byte token length header could not be read. This library parses the TDS wire protocol itself instead of using a driver, so it validates every field boundary and refuses to continue when the payload ends mid-token. It indicates a corrupt, truncated, or hostile server response rather than a caller mistake.

Source

Thrown at plugins/services/mssql_raw.go:335

			}
			result.sawLoginAck = true
			pos = next
		case tdsTokenDone, tdsTokenDoneProc, tdsTokenDoneInProc:
			if pos+12 > len(payload) {
				return false, fmt.Errorf("mssql: truncated done token")
			}
			status := binary.LittleEndian.Uint16(payload[pos : pos+2])
			return status&(tdsDoneError|tdsDoneSrvError) == 0, nil
		default:
			return false, fmt.Errorf("mssql: unexpected login token 0x%02x", token)
		}
	}
	return false, nil
}

func mssqlParseErrorToken(payload []byte, pos int) (mssqlRawError, int, error) {
	if pos+2 > len(payload) {
		return mssqlRawError{}, pos, fmt.Errorf("mssql: truncated error token")
	}
	size := int(binary.LittleEndian.Uint16(payload[pos : pos+2]))
	end := pos + 2 + size
	if size < 6 || end > len(payload) || pos+8 > len(payload) {
		return mssqlRawError{}, pos, fmt.Errorf("mssql: invalid error token size")
	}
	pos += 2
	number := int32(binary.LittleEndian.Uint32(payload[pos : pos+4]))
	pos += 4
	pos += 2
	message, next, err := mssqlReadUSVarChar(payload, pos)
	if err != nil {
		return mssqlRawError{}, pos, err
	}
	return mssqlRawError{number: number, message: message}, end, mssqlEnsureSkipBVarStrings(payload, next, end)
}

func mssqlSkipUSVarError(payload []byte, pos int) (int, error) {

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Retry the connection; a truncated response is usually transient network corruption.
  2. Verify the host:port actually points at a Microsoft SQL Server (TDS) endpoint, not another service.
  3. Capture the raw response (tcpdump/Wireshark) and check whether a middlebox is cutting the TCP stream.
  4. Upgrade or patch the server if a known TDS bug emits malformed ERROR tokens.

Example fix

// before: assume payload contains full tokens
for pos < len(payload) {
    err, next, _ := mssqlParseErrorToken(payload, pos)
    pos = next
}
// after: check remaining bytes for the 2-byte length header first
for pos+2 <= len(payload) {
    err, next, perr := mssqlParseErrorToken(payload, pos)
    if perr != nil {
        return fmt.Errorf("malformed login response at offset %d: %w", pos, perr)
    }
    pos = next
}
Defensive patterns

Strategy: try-catch

Validate before calling

if len(payload) < pos+2 {
    return fmt.Errorf("payload too short for ERROR token header at offset %d", pos)
}

Type guard

func hasErrorTokenHeader(payload []byte, pos int) bool {
    return pos+2 <= len(payload)
}

Try / catch

err, next, perr := mssqlParseErrorToken(payload, pos)
if perr != nil {
    // close connection; do not reuse partial parse state
    conn.Close()
    return fmt.Errorf("malformed ERROR token at %d: %w", pos, perr)
}

Prevention

When it happens

Trigger: Calling mssqlParseLoginTokens on a payload where the byte stream ends exactly at (or inside) the 2-byte length prefix of an ERROR token (0xAA), i.e. pos+2 > len(payload).

Common situations: A proxy, load balancer, or TLS terminator cut the server response short; a non-MSSQL service is answering on the SQL port and returns garbage; a fuzzer or malicious server sends a deliberately truncated packet; a custom packet-size/timeout dropped the tail of the login response.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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