TechnitiumSoftware/DnsServer · error · ArgumentException
Ending address must be greater than starting address.
Error message
Ending address must be greater than starting address.
What it means
Thrown by the DHCP Scope constructor (which delegates to ChangeNetwork) and by ChangeNetwork directly when the ending IPv4 address is not strictly greater than the starting address after both are converted to 32-bit unsigned integers. It prevents creation of a degenerate or empty address pool where no host address could ever be handed out.
Source
Thrown at DnsServerCore/Dhcp/Scope.cs:1447
#region public
public void ChangeNetwork(IPAddress startingAddress, IPAddress endingAddress, IPAddress subnetMask)
{
if (startingAddress.AddressFamily != AddressFamily.InterNetwork)
throw new ArgumentException("The address must be an IPv4 address: " + startingAddress.ToString(), nameof(startingAddress));
if (endingAddress.AddressFamily != AddressFamily.InterNetwork)
throw new ArgumentException("The address must be an IPv4 address: " + endingAddress.ToString(), nameof(endingAddress));
if (subnetMask.AddressFamily != AddressFamily.InterNetwork)
throw new ArgumentException("The address must be an IPv4 address: " + subnetMask.ToString(), nameof(subnetMask));
uint startingAddressNumber = startingAddress.ConvertIpToNumber();
uint endingAddressNumber = endingAddress.ConvertIpToNumber();
if (startingAddressNumber >= endingAddressNumber)
throw new ArgumentException("Ending address must be greater than starting address.");
_startingAddress = startingAddress;
_endingAddress = endingAddress;
_subnetMask = subnetMask;
//compute other parameters
uint subnetMaskNumber = _subnetMask.ConvertIpToNumber();
uint networkAddressNumber = startingAddressNumber & subnetMaskNumber;
uint broadcastAddressNumber = networkAddressNumber | ~subnetMaskNumber;
if (networkAddressNumber == startingAddressNumber)
throw new ArgumentException("Starting address cannot be same as the network address.");
if (broadcastAddressNumber == endingAddressNumber)
throw new ArgumentException("Ending address cannot be same as the broadcast address.");
_networkAddress = IPAddressExtensions.ConvertNumberToIp(networkAddressNumber);
_broadcastAddress = IPAddressExtensions.ConvertNumberToIp(broadcastAddressNumber);View on GitHub (pinned to d0484b6c1e)
Solutions
- Sort or compare the two addresses numerically before constructing the Scope so endingAddress is strictly greater than startingAddress.
- Re-check the argument order in the call site; startingAddress is the third positional parameter and endingAddress the fourth.
- If deriving the range from a CIDR, compute start = network+1 and end = broadcast-1 rather than reusing the network address as a bound.
- Confirm byte order: IPAddress.GetAddressBytes() is network order; convert with BitConverter in big-endian (or reverse) to compare as the library does.
Example fix
// before
var scope = new Scope(name, true,
IPAddress.Parse("192.168.1.50"), // start
IPAddress.Parse("192.168.1.10"), // end <= start -> throws
IPAddress.Parse("255.255.255.0"), log, dhcpServer);
// after
var start = IPAddress.Parse("192.168.1.10");
var end = IPAddress.Parse("192.168.1.50");
if (ToUint(end) <= ToUint(start)) throw new InvalidOperationException("bad range");
var scope = new Scope(name, true, start, end,
IPAddress.Parse("255.255.255.0"), log, dhcpServer);
static uint ToUint(IPAddress a){ var b=a.GetAddressBytes(); return (uint)(b[0]<<24|b[1]<<16|b[2]<<8|b[3]); } Defensive patterns
Strategy: validation
Validate before calling
static uint ToUint(IPAddress a){ var b=a.GetAddressBytes(); return (uint)((b[0]<<24)|(b[1]<<16)|(b[2]<<8)|b[3]); }
static bool IsValidRange(IPAddress start, IPAddress end){
return ToUint(end) > ToUint(start);
}
// before constructing the Scope:
if (!IsValidRange(startingAddress, endingAddress))
throw new ConfigurationException("endingAddress must be greater than startingAddress"); Type guard
static bool IsOrderedIpv4Range(IPAddress start, IPAddress end)
=> start.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork
&& end.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork
&& ToUint(end) > ToUint(start); Try / catch
try { var scope = new Scope(name, true, start, end, mask, log, dhcpServer); }
catch (ArgumentException ex) when (ex.Message.Contains("Ending address must be greater"))
{ /* re-prompt user with corrected range */ } Prevention
- Always compute start/end from a single source (CIDR) so order is guaranteed.
- Unit-test scope creation with reversed/equal addresses to confirm your validation fires first.
- Keep start/end as IPAddress throughout; never reconstruct from int without fixing byte order.
When it happens
Trigger: Calling 'new Scope(name, enabled, startingAddress, endingAddress, subnetMask, log, dhcpServer)' or 'scope.ChangeNetwork(start, end, mask)' with end numerically <= start. This includes equal addresses, reversed order (start=192.168.1.50, end=192.168.1.10), or byte-order mistakes when constructing the IPAddress from an integer.
Common situations: Form fields supplied in the wrong order, swapped positional arguments, copying a CIDR host range where both bounds resolve to the same IP, or feeding IPAddress.Parse a hex/decimal value whose byte order produces a lower ending number than expected.
Related errors
- Exclusion starting address must be in scope range.
- Exclusion ending address must be in scope range.
- Reserved address must be in scope range.
- The address must be an IPv4 address: {startingAddress}
- The address must be an IPv4 address: {endingAddress}
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/bd3bb69c9b51aa76.
Report an issue: GitHub.