TechnitiumSoftware/DnsServer · error · ArgumentException
Transaction ID must be 4 bytes.
Error message
Transaction ID must be 4 bytes.
What it means
Constructor argument guard in DhcpMessage: the transaction ID (xid) must be exactly 4 bytes. RFC 2131 defines the xid field as a 4-octet value used to match request/reply pairs, so any other length is invalid wire data.
Source
Thrown at DnsServerCore/Dhcp/DhcpMessage.cs:116
if (ciaddr.AddressFamily != AddressFamily.InterNetwork)
throw new ArgumentException("Address family not supported.", nameof(ciaddr));
if (yiaddr.AddressFamily != AddressFamily.InterNetwork)
throw new ArgumentException("Address family not supported.", nameof(yiaddr));
if (siaddr.AddressFamily != AddressFamily.InterNetwork)
throw new ArgumentException("Address family not supported.", nameof(siaddr));
if (giaddr.AddressFamily != AddressFamily.InterNetwork)
throw new ArgumentException("Address family not supported.", nameof(giaddr));
ArgumentNullException.ThrowIfNull(clientHardwareAddress);
if (clientHardwareAddress.Length > 16)
throw new ArgumentException("Client hardware address cannot exceed 16 bytes.", nameof(clientHardwareAddress));
if (xid.Length != 4)
throw new ArgumentException("Transaction ID must be 4 bytes.", nameof(xid));
if (secs.Length != 2)
throw new ArgumentException("Seconds elapsed must be 2 bytes.", nameof(secs));
_op = op;
_htype = hardwareAddressType;
_hlen = Convert.ToByte(clientHardwareAddress.Length);
_hops = 0;
_xid = xid;
_secs = secs;
_flags = flags;
_ciaddr = ciaddr;
_yiaddr = yiaddr;
_siaddr = siaddr;
_giaddr = giaddr;View on GitHub (pinned to d0484b6c1e)
Solutions
- Generate xid as exactly 4 bytes (e.g. BitConverter.GetBytes(RandomNumberGenerator.GetInt32(int.MinValue, int.MaxValue)) or NextBytes on a 4-byte array).
- When forwarding, copy the original 4-byte xid unchanged.
- Validate xid.Length == 4 before constructing.
- Do not substitute a GUID/16-byte token for xid.
Example fix
// before byte[] xid = Guid.NewGuid().ToByteArray(); // 16 bytes var msg = new DhcpMessage(op, htype, xid, secs, flags, ...); // throws [216] // after byte[] xid = new byte[4]; RandomNumberGenerator.Fill(xid); var msg = new DhcpMessage(op, htype, xid, secs, flags, ...);
Defensive patterns
Strategy: validation
Validate before calling
if (xid is null) throw new ArgumentNullException(nameof(xid));
if (xid.Length != 4) throw new ArgumentException("Transaction ID (xid) must be exactly 4 bytes.", nameof(xid));
var msg = new DhcpMessage(op, htype, xid, secs, flags, ciaddr, yiaddr, siaddr, giaddr, chaddr, sname, file, opts); Type guard
static bool IsValidXid(byte[] xid) =>
xid is not null && xid.Length == 4; Prevention
- Generate xid as exactly 4 random bytes.
- When forwarding, reuse the original 4-byte xid unchanged.
- Never substitute a GUID (16 bytes) for xid.
When it happens
Trigger: Calling the DhcpMessage constructor with an xid byte array whose Length is not 4.
Common situations: Generating xid with the wrong RNG width (e.g. 16 bytes / a GUID); passing a uint without converting to 4 bytes; copying xid from a truncated/extended buffer.
Related errors
- Client hardware address cannot exceed 16 bytes.
- Seconds elapsed must be 2 bytes.
- Server host name cannot exceed 63 bytes.
- Boot file name cannot exceed 127 bytes.
- Address family not supported.
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/6c4869c4dd955485.
Report an issue: GitHub.