TechnitiumSoftware/DnsServer · warning · DhcpServerException

No reserved lease was found for client identifier: {clientId

Error message

No reserved lease was found for client identifier: {clientIdentifier}

What it means

Thrown by Scope.ConvertToDynamicLease(ClientIdentifierOption) when no lease exists for the identifier OR the existing lease is not Reserved. TryGetValue false or lease.Type != LeaseType.Reserved both raise this DhcpServerException.

Source

Thrown at DnsServerCore/Dhcp/Scope.cs:1596

            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);
            bW.Write(_enabled);
            _startingAddress.WriteTo(bW);
            _endingAddress.WriteTo(bW);
            _subnetMask.WriteTo(bW);
            bW.Write(_leaseTimeDays);
            bW.Write(_leaseTimeHours);

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Ensure a Reserved lease exists for the ClientIdentifierOption on this scope.
  2. Skip the call if the lease is already Dynamic.
  3. Reconcile state by removing and re-adding if needed.
  4. Construct the ClientIdentifierOption with the stored hardware type.

Example fix

// before
scope.ConvertToDynamicLease(clientId);

// after
if (scope.Leases.TryGetValue(clientId, out var l) && l.Type == LeaseType.Reserved)
    scope.ConvertToDynamicLease(clientId);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!scope.Leases.TryGetValue(clientIdentifier, out var lease) || lease.Type != LeaseType.Reserved) return;

Type guard

static bool HasReservedLeaseForClient(Scope scope, ClientIdentifierOption id)
    => scope.Leases.TryGetValue(id, out var l) && l.Type == LeaseType.Reserved;

Try / catch

try { scope.ConvertToDynamicLease(clientIdentifier); }
catch (DhcpServerException ex) when (ex.Message.Contains("No reserved lease"))
{ /* lease absent or already dynamic */ }

Prevention

When it happens

Trigger: Calling scope.ConvertToDynamicLease(clientId) for an unknown client identifier, a client whose lease is already Dynamic, or an identifier with a mismatched hardware-address type.

Common situations: Demoting a non-reserved client, repeated demotion, or identifier byte/type mismatch with stored lease.

Related errors


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