TechnitiumSoftware/DnsServer · warning · DhcpServerException

No dynamic lease was found for client identifier: {clientIde

Error message

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

What it means

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

Source

Thrown at DnsServerCore/Dhcp/Scope.cs:1570

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

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

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

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

            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;
                }
            }

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Ensure a Dynamic lease exists for the ClientIdentifierOption on this scope.
  2. Skip the call if the lease is already Reserved.
  3. Create a reservation directly via the reservation API when no dynamic lease exists.
  4. Build the ClientIdentifierOption with the same hardware type as the stored lease.

Example fix

// before
scope.ConvertToReservedLease(clientId);

// after
if (scope.Leases.TryGetValue(clientId, out var l) && l.Type == LeaseType.Dynamic)
    scope.ConvertToReservedLease(clientId);
else
    _log.Info("no dynamic lease to convert; add reservation explicitly");
Defensive patterns

Strategy: try-catch

Validate before calling

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

Type guard

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

Try / catch

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

Prevention

When it happens

Trigger: Calling scope.ConvertToReservedLease(clientId) for an unknown client identifier, a client whose lease already became Reserved, or an identifier constructed with a mismatched hardware-address type.

Common situations: Re-reserving an already-reserved client, converting before the client has obtained a dynamic lease, or identifier byte/type mismatch with stored data.

Related errors


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