TechnitiumSoftware/DnsServer · warning · DhcpServerException

No reserved lease was found for hardware address: {hardwareA

Error message

No reserved lease was found for hardware address: {hardwareAddress}

What it means

Thrown by Scope.ConvertToDynamicLease(string hardwareAddress) when no RESERVED lease matches the hardware address. Only a Reserved lease can be demoted to Dynamic; an absent or already-dynamic lease triggers this error.

Source

Thrown at DnsServerCore/Dhcp/Scope.cs:1590

            ConvertToReservedLease(lease);
        }

        public void ConvertToDynamicLease(string hardwareAddress)
        {
            byte[] hardwareAddressBytes = Lease.ParseHardwareAddress(hardwareAddress);

            foreach (KeyValuePair<ClientIdentifierOption, Lease> entry in _leases)
            {
                Lease lease = entry.Value;

                if ((lease.Type == LeaseType.Reserved) && lease.HardwareAddress.SequenceEqual(hardwareAddressBytes))
                {
                    ConvertToDynamicLease(lease);
                    return;
                }
            }

            throw new DhcpServerException("No reserved lease was found for hardware address: " + hardwareAddress);
        }

        public void ConvertToDynamicLease(ClientIdentifierOption clientIdentifier)
        {
            if (!_leases.TryGetValue(clientIdentifier, out Lease lease) || (lease.Type != LeaseType.Reserved))
                throw new DhcpServerException("No reserved lease was found for client identifier: " + clientIdentifier.ToString());

            ConvertToDynamicLease(lease);
        }

        public void WriteTo(Stream s)
        {
            BinaryWriter bW = new BinaryWriter(s);

            bW.Write(Encoding.ASCII.GetBytes("SC"));
            bW.Write((byte)10); //version

            s.WriteShortString(_name);

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Confirm a Reserved lease exists for the MAC on this scope before demoting.
  2. If the lease is already Dynamic, no conversion is needed.
  3. Remove and re-add as dynamic if state is inconsistent.
  4. Verify the MAC string format against the stored value.

Example fix

// before
scope.ConvertToDynamicLease(mac); // throws if not reserved

// after
var lease = scope.Leases.FirstOrDefault(l => l.Type == LeaseType.Reserved && l.HardwareAddress.SequenceEqual(Lease.ParseHardwareAddress(mac)));
if (lease != null) scope.ConvertToDynamicLease(mac);
Defensive patterns

Strategy: validation

Validate before calling

byte[] mac = Lease.ParseHardwareAddress(macString);
bool convertible = scope.Leases.Any(l => l.Type == LeaseType.Reserved && l.HardwareAddress.SequenceEqual(mac));
if (!convertible) return;

Type guard

static bool HasReservedLeaseForHardware(Scope scope, string mac){
    var bytes = Lease.ParseHardwareAddress(mac);
    return scope.Leases.Any(l => l.Type == LeaseType.Reserved && l.HardwareAddress.SequenceEqual(bytes));
}

Try / catch

try { scope.ConvertToDynamicLease(macString); }
catch (DhcpServerException ex) when (ex.Message.Contains("No reserved lease"))
{ /* nothing reserved to demote */ }

Prevention

When it happens

Trigger: Calling scope.ConvertToDynamicLease(mac) where the matching lease is Dynamic, Static, or missing. The loop only converts when lease.Type == LeaseType.Reserved and the MAC matches.

Common situations: Demoting a client that has no reservation, re-demoting an already-dynamic lease, or MAC format mismatch with stored HardwareAddress.

Related errors


AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13). Data as JSON: /api/errors/db34a55f930d949d. Report an issue: GitHub.