TechnitiumSoftware/DnsServer · error · InvalidOperationException
Cannot set {type} record at zone apex.
Error message
Cannot set {type} record at zone apex. What it means
Thrown as InvalidOperationException by PrimaryZone.SetRecords() when the requested type is CNAME or DS. A CNAME at the zone apex is illegal (RFC 1034: apex must have SOA/NS) and a DS record is managed by the parent zone, not set locally at the apex. This is a programming/usage error, not an operational condition.
Source
Thrown at DnsServerCore/Dns/Zones/PrimaryZone.cs:2533
case DnsResourceRecordType.APP:
throw new DnsServerException("The record type is not supported by DNSSEC signed primary zones.");
default:
foreach (DnsResourceRecord record in records)
{
if (record.GetAuthGenericRecordInfo().Disabled)
throw new DnsServerException("Cannot set records: disabling records in a signed zones is not supported.");
}
break;
}
}
switch (type)
{
case DnsResourceRecordType.CNAME:
case DnsResourceRecordType.DS:
throw new InvalidOperationException("Cannot set " + type.ToString() + " record at zone apex.");
case DnsResourceRecordType.SOA:
if ((records.Count != 1) || !records[0].Name.Equals(_name, StringComparison.OrdinalIgnoreCase))
throw new InvalidOperationException("Invalid SOA record.");
DnsResourceRecord newSoaRecord = records[0];
DnsSOARecordData newSoa = newSoaRecord.RDATA as DnsSOARecordData;
if (newSoaRecord.OriginalTtlValue > newSoa.Expire)
throw new DnsServerException("Cannot set record: TTL cannot be greater than SOA EXPIRE.");
if (newSoa.Retry > newSoa.Refresh)
throw new DnsServerException("Cannot set record: SOA RETRY cannot be greater than SOA REFRESH.");
if (newSoa.Refresh > newSoa.Expire)
throw new DnsServerException("Cannot set record: SOA REFRESH cannot be greater than SOA EXPIRE.");
//remove any record info except serial date scheme and commentsView on GitHub (pinned to d0484b6c1e)
Solutions
- Never call SetRecords with CNAME or DS on a primary zone; CNAME is illegal at the apex and DS belongs in the parent zone.
- Guard the call site with a type check that skips CNAME/DS.
- Use the zone's specific APIs (parent-zone DS management, non-apex CNAME handling) instead of SetRecords for these types.
Example fix
// before
zone.SetRecords(type, records); // throws for CNAME/DS
// after
if (type != DnsResourceRecordType.CNAME && type != DnsResourceRecordType.DS)
zone.SetRecords(type, records); Defensive patterns
Strategy: type-guard
Validate before calling
if (type == DnsResourceRecordType.CNAME || type == DnsResourceRecordType.DS)
throw new ArgumentException($"{type} cannot be set at the zone apex.");
zone.SetRecords(type, records); Type guard
static bool IsApexSettable(DnsResourceRecordType t) =>
t != DnsResourceRecordType.CNAME && t != DnsResourceRecordType.DS; Try / catch
try { zone.SetRecords(type, records); }
catch (InvalidOperationException ex) when (ex.Message.Contains("record at zone apex"))
{ Log.Error($"{type} is illegal at the apex: {ex.Message}"); } Prevention
- Never route CNAME/DS through SetRecords on a primary zone.
- Model apex record types explicitly in importers.
- Treat InvalidOperationException from SetRecords as a caller bug, not a runtime condition.
When it happens
Trigger: Calling SetRecords(DnsResourceRecordType.CNAME, ...) or SetRecords(DnsResourceRecordType.DS, ...) on a primary zone (these types resolve to the apex-rejection branch in the switch).
Common situations: Generic record-management code that iterates all record types and calls SetRecords for each without excluding CNAME/DS; importing a foreign zone file that places a CNAME at the apex.
Related errors
- Cannot set DS record at zone apex.
- Invalid SOA record.
- Cannot set DNSSEC records.
- Cannot add record: use SetRecords() for {type} record
- Cannot add DNSSEC record.
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/b76c7c9b9672fd38.
Report an issue: GitHub.