TechnitiumSoftware/DnsServer · error · InvalidOperationException
Cannot add record: use SetRecords() for {type} record.
Error message
Cannot add record: use SetRecords() for {type} record. What it means
AuthZone.AddRecord explicitly rejects CNAME, DNAME, and SOA record types with InvalidOperationException. These types are singleton-per-name records with special semantics: SOA is the zone's Start of Authority (one per zone), and CNAME/DNAME are exclusive types that cannot coexist with others. The library requires you to use SetRecords() instead, which performs the proper validation and atomic replacement logic for these singleton types.
Source
Thrown at DnsServerCore/Dns/Zones/AuthZone.cs:312
}
updatedRecords.AddRange(newRRSigRecords);
deleted = deletedRecords;
return updatedRecords;
});
deletedRRSigRecords = deleted;
}
internal void AddRecord(DnsResourceRecord record, out IReadOnlyList<DnsResourceRecord> addedRecords, out IReadOnlyList<DnsResourceRecord> deletedRecords)
{
switch (record.Type)
{
case DnsResourceRecordType.CNAME:
case DnsResourceRecordType.DNAME:
case DnsResourceRecordType.SOA:
throw new InvalidOperationException("Cannot add record: use SetRecords() for " + record.Type.ToString() + " record.");
default:
if (_entries.ContainsKey(DnsResourceRecordType.CNAME))
throw new InvalidOperationException("Cannot add record: a CNAME record cannot exists with other record types for the same name.");
break;
}
List<DnsResourceRecord> added = new List<DnsResourceRecord>();
List<DnsResourceRecord> deleted = new List<DnsResourceRecord>();
addedRecords = added;
deletedRecords = deleted;
_entries.AddOrUpdate(record.Type, delegate (DnsResourceRecordType key)
{
added.Add(record);
return [record];View on GitHub (pinned to d0484b6c1e)
Solutions
- Use SetRecords(type, [record]) for CNAME, DNAME, and SOA records instead of AddRecord(record).
- Add a type check in calling code: if the record type is CNAME/DNAME/SOA, route to SetRecords; otherwise use AddRecord.
- For SOA modifications specifically, use the zone's dedicated SOA management methods (e.g., increment serial via the zone's built-in mechanism).
Example fix
// before
zone.AddRecord(new DnsResourceRecord(name, DnsResourceRecordType.SOA, ...));
// throws: use SetRecords() for SOA record
// after
zone.SetRecords(DnsResourceRecordType.SOA, new[] { soaRecord }); Defensive patterns
Strategy: type-guard
Validate before calling
static bool RequiresSetRecords(DnsResourceRecordType type)
=> type == DnsResourceRecordType.CNAME
|| type == DnsResourceRecordType.DNAME
|| type == DnsResourceRecordType.SOA;
if (RequiresSetRecords(record.Type))
zone.SetRecords(record.Type, new[] { record });
else
zone.AddRecord(record); Type guard
static bool CanAddRecord(DnsResourceRecordType type)
=> type != DnsResourceRecordType.CNAME
&& type != DnsResourceRecordType.DNAME
&& type != DnsResourceRecordType.SOA; Prevention
- Route CNAME, DNAME, and SOA through SetRecords in all record-management code.
- Build a type-dispatch helper that automatically selects AddRecord vs SetRecords.
- Document the singleton-type restriction in API handler code.
When it happens
Trigger: Calling the internal AddRecord method (or the public AddRecord wrapper) with a DnsResourceRecord whose Type is CNAME, DNAME, or SOA. This happens when application code uses AddRecord for a record type that must be managed exclusively via SetRecords.
Common situations: Programmatic zone management code that treats all record types uniformly through AddRecord; migration scripts that add records in a loop without type-specific routing; web API handlers that incorrectly route SOA/CNAME/DNAME modifications through AddRecord.
Related errors
- Cannot update record: use SetRecords() for {type} record
- Old and new record types do not match.
- Cannot update record: the old record does not exists.
- Zone was not found for domain: {key}
- The domain name '<domain>' does not belong to the zone: <zon
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/de477baf7c1e88c4.
Report an issue: GitHub.