TechnitiumSoftware/DnsServer · error · DnsServerException

Cannot delete private key: only keys with Generated state ca

Error message

Cannot delete private key: only keys with Generated state can be deleted.

What it means

Thrown by DeletePrivateKey when the matched key's State is not Generated. Only keys still in the Generated state (created but never published) can be safely removed; deleting a Published/Ready/Active/Retired key would corrupt the DNSKEY chain, so the library refuses it.

Source

Thrown at DnsServerCore/Dns/Zones/PrimaryZone.cs:1099

                privateKey.RolloverDays = rolloverDays;

                return privateKey;
            }
        }

        public void DeletePrivateKey(ushort keyTag)
        {
            if (_dnssecStatus == AuthZoneDnssecStatus.Unsigned)
                throw new DnsServerException("The zone must be signed.");

            lock (_dnssecPrivateKeys)
            {
                if (!_dnssecPrivateKeys.TryGetValue(keyTag, out DnssecPrivateKey privateKey))
                    throw new DnsServerException("Cannot delete private key: no such private key was found.");

                if (privateKey.State != DnssecPrivateKeyState.Generated)
                    throw new DnsServerException("Cannot delete private key: only keys with Generated state can be deleted.");

                _dnssecPrivateKeys.Remove(keyTag);
            }
        }

        public void PublishAllGeneratedKeys()
        {
            if (_dnssecStatus == AuthZoneDnssecStatus.Unsigned)
                throw new DnsServerException("The zone must be signed.");

            List<DnssecPrivateKey> generatedPrivateKeys = new List<DnssecPrivateKey>();
            List<DnsResourceRecord> newDnsKeyRecords = new List<DnsResourceRecord>();

            uint dnsKeyTtl = GetDnsKeyTtl();

            lock (_dnssecPrivateKeys)
            {
                foreach (KeyValuePair<ushort, DnssecPrivateKey> privateKeyEntry in _dnssecPrivateKeys)

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Before deleting, check the key's State and only delete when State == DnssecPrivateKeyState.Generated.
  2. For already-published keys, retire them through the rollover/retire workflow (RolloverDnsKey / RetireDnsKeyAsync) rather than deleting outright.
  3. Surface a clear UI message explaining only Generated keys are deletable.

Example fix

// before
zone.DeletePrivateKey(keyTag);

// after
var key = zone.DnssecPrivateKeys.FirstOrDefault(k => k.KeyTag == keyTag);
if (key is null) return;
if (key.State != DnssecPrivateKeyState.Generated)
    throw new InvalidOperationException($"Key {keyTag} is {key.State}; only Generated keys can be deleted.");
zone.DeletePrivateKey(keyTag);
Defensive patterns

Strategy: type-guard

Validate before calling

// Only delete keys that are still in the Generated state
var key = zone.DnssecPrivateKeys.FirstOrDefault(k => k.KeyTag == keyTag);
if (key is null) return;
if (key.State != DnssecPrivateKeyState.Generated)
    throw new InvalidOperationException($"Key {keyTag} state is {key.State}; only Generated keys can be deleted.");
zone.DeletePrivateKey(keyTag);

Type guard

static bool IsKeyDeletable(DnssecPrivateKey key) =>
    key.State == DnssecPrivateKeyState.Generated;

Try / catch

try
{
    zone.DeletePrivateKey(keyTag);
}
catch (DnsServerException ex) when (ex.Message.Contains("only keys with Generated state"))
{
    // key already advanced; retire it via the rollover workflow instead
}

Prevention

When it happens

Trigger: Calling DeletePrivateKey on a key whose State is Published, Ready, Active, Retired, Dead, Revoked, or Removed rather than Generated.

Common situations: Trying to delete a key that has already been published or activated via PublishAllGeneratedKeys/ActivateKskDnsKey; housekeeping that targets all keys indiscriminately.

Related errors


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