TechnitiumSoftware/DnsServer · error · DnsServerException

Failed to add {(privateKey.KeyType == DnssecPrivateKeyType.K

Error message

Failed to add {(privateKey.KeyType == DnssecPrivateKeyType.KeySigningKey ? "KSK" : "ZSK")} private key: key tag collision. Please generate another private key and try again.

What it means

Thrown by AddPrivateKey when _dnssecPrivateKeys.TryAdd fails because a key with the same KeyTag already exists. Unlike GenerateAndAddPrivateKey, this method imports a caller-supplied key and does not retry, so a single collision is fatal.

Source

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

                lock (_dnssecPrivateKeys)
                {
                    if (_dnssecPrivateKeys.TryAdd(privateKey.KeyTag, privateKey))
                        return privateKey;
                }
            }

            throw new DnsServerException("Failed to add private key: key tag collision. Please try again.");
        }

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

            lock (_dnssecPrivateKeys)
            {
                if (!_dnssecPrivateKeys.TryAdd(privateKey.KeyTag, privateKey))
                    throw new DnsServerException($"Failed to add {(privateKey.KeyType == DnssecPrivateKeyType.KeySigningKey ? "KSK" : "ZSK")} private key: key tag collision. Please generate another private key and try again.");
            }
        }

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

                privateKey.RolloverDays = rolloverDays;

                return privateKey;
            }
        }

        public void DeletePrivateKey(ushort keyTag)
        {

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Before adding, enumerate the zone's DnssecPrivateKeys and verify no entry shares the incoming KeyTag.
  2. If the key already exists and is the intended one, skip the add; otherwise delete the conflicting key first.
  3. Generate a fresh key with GenerateAndAddPrivateKey instead of importing one whose tag clashes.

Example fix

// before
zone.AddPrivateKey(privateKey);

// after
bool exists = zone.DnssecPrivateKeys.Any(k => k.KeyTag == privateKey.KeyTag);
if (!exists)
    zone.AddPrivateKey(privateKey);
else
    Console.WriteLine($"KeyTag {privateKey.KeyTag} already present; skipping.");
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the incoming KeyTag is not already present
bool exists = zone.DnssecPrivateKeys.Any(k => k.KeyTag == privateKey.KeyTag);
if (!exists)
    zone.AddPrivateKey(privateKey);

Type guard

static bool KeyTagIsFree(ApexZone zone, ushort keyTag) =>
    !zone.DnssecPrivateKeys.Any(k => k.KeyTag == keyTag);

Try / catch

try
{
    zone.AddPrivateKey(privateKey);
}
catch (DnsServerException ex) when (ex.Message.Contains("key tag collision"))
{
    // delete the conflicting key or generate a fresh one instead
}

Prevention

When it happens

Trigger: Calling AddPrivateKey with a DnssecPrivateKey whose KeyTag matches a key already stored on the zone.

Common situations: Re-importing a key that is already present; restoring from a backup that overlaps with the live key set; adding both members of a pre-computed KSK/ZSK pair whose tags coincide.

Related errors


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