TechnitiumSoftware/DnsServer · error · ArgumentException
Starting address cannot be same as the network address.
Error message
Starting address cannot be same as the network address.
What it means
Thrown by Scope construction / ChangeNetwork when the starting address equals the network address (start AND subnetMask). A DHCP pool must never offer the network identifier itself (e.g. 192.168.1.0/24) to a client, so the library rejects it up front.
Source
Thrown at DnsServerCore/Dhcp/Scope.cs:1459
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);
_lastAddressOfferedLock.Wait();
try
{
_lastAddressOffered = IPAddressExtensions.ConvertNumberToIp(startingAddressNumber - 1u);
}
finally
{
_lastAddressOfferedLock.Release();
}
}
View on GitHub (pinned to d0484b6c1e)
Solutions
- Increment the starting address above the network address (network + 1) before constructing the Scope.
- Recompute: if (start & mask) == start, bump start by one host.
- For very small subnets (/31, /32) use a larger block since there are no usable hosts between network and broadcast.
- Validate the mask itself; a malformed mask with all-zero host bits makes every address equal the network address.
Example fix
// before
var net = IPAddress.Parse("192.168.1.0");
var scope = new Scope(name, true, net,
IPAddress.Parse("192.168.1.254"),
IPAddress.Parse("255.255.255.0"), log, dhcpServer); // throws
// after
var start = IPAddress.Parse("192.168.1.1"); // network + 1
var scope = new Scope(name, true, start,
IPAddress.Parse("192.168.1.254"),
IPAddress.Parse("255.255.255.0"), log, dhcpServer); 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 IPAddress Increment(IPAddress a){ var u=ToUint(a)+1u; return new IPAddress(new byte[]{(byte)(u>>24),(byte)(u>>16),(byte)(u>>8),(byte)u}); }
uint network = ToUint(start) & ToUint(mask);
if (network == ToUint(start)) startingAddress = Increment(start); // bump off network Type guard
static bool StartIsNotNetworkAddress(IPAddress start, IPAddress mask)
=> (ToUint(start) & ToUint(mask)) != ToUint(start); Try / catch
try { scope.ChangeNetwork(start, end, mask); }
catch (ArgumentException ex) when (ex.Message.Contains("network address"))
{ start = Increment(start); scope.ChangeNetwork(start, end, mask); } Prevention
- Derive start as network+1 and end as broadcast-1 from the CIDR.
- Reject masks with zero host bits before building a pool.
- Add a config sanity check that start != network in your validation pipeline.
When it happens
Trigger: Passing a startingAddress that is the subnet's base address: e.g. start=192.168.1.0 with mask 255.255.255.0, or start=10.0.0.0 with mask 255.0.0.0. Also triggered when a /31 or /32 mask collapses network onto the supplied start, or when auto-generating start from the network address without incrementing.
Common situations: Generating ranges from CIDR notation but forgetting to skip the network address; config files that list the subnet base as the first usable host; tooling that sets start = networkAddress verbatim.
Related errors
- Ending address cannot be same as the broadcast address.
- The address must be an IPv4 address: {startingAddress}
- The address must be an IPv4 address: {endingAddress}
- The address must be an IPv4 address: {subnetMask}
- Ending address must be greater than starting address.
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/8a4153caa7158ec3.
Report an issue: GitHub.