TechnitiumSoftware/DnsServer · error · InvalidOperationException

Invalid SOA record.

Error message

Invalid SOA record.

What it means

CatalogZone.SetRecords for SOA validates that exactly one SOA record is provided and that its owner name matches the catalog zone's own name (_name). If records.Count != 1 or the record name does not match, it throws InvalidOperationException. Catalog zones have a fixed SOA with specific mandated values; the method also overwrites MNAME and RNAME with 'invalid' per RFC 9432, keeping only serial/timer values from the input.

Source

Thrown at DnsServerCore/Dns/Zones/CatalogZone.cs:404

            throw new DnsServerException("Failed to generate unique label for the given domain name '" + domain + "'. Please try again.");
        }

        #endregion

        #region public

        public override string GetZoneTypeName()
        {
            return "Catalog";
        }

        public override void SetRecords(DnsResourceRecordType type, IReadOnlyList<DnsResourceRecord> records)
        {
            switch (type)
            {
                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;

                    //reset fixed record values
                    DnsSOARecordData modifiedSoa = new DnsSOARecordData("invalid", "invalid", newSoa.Serial, newSoa.Refresh, newSoa.Retry, newSoa.Expire, newSoa.Minimum);
                    DnsResourceRecord modifiedSoaRecord = new DnsResourceRecord(_name, DnsResourceRecordType.SOA, DnsClass.IN, 0, modifiedSoa) { Tag = newSoaRecord.Tag };

                    base.SetRecords(type, [modifiedSoaRecord]);
                    break;

                default:
                    throw new InvalidOperationException("Cannot set records in Catalog zone.");
            }

        }

        public override bool AddRecord(DnsResourceRecord record)

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Ensure exactly one SOA record is passed with its Name equal to the catalog zone name.
  2. If importing via zone transfer, normalize the SOA record name to the local zone name before calling SetRecords.
  3. Validate: records.Count == 1 && records[0].Name.Equals(catalogZone.Name, StringComparison.OrdinalIgnoreCase) before the call.

Example fix

// before
catalogZone.SetRecords(DnsResourceRecordType.SOA, soaRecords);
// throws if soaRecords.Count != 1 or name mismatch

// after
var soa = new DnsResourceRecord(
    catalogZone.Name, // must match zone name
    DnsResourceRecordType.SOA,
    DnsClass.IN, 0, soaData);
catalogZone.SetRecords(DnsResourceRecordType.SOA, new[] { soa });
Defensive patterns

Strategy: validation

Validate before calling

if (records.Count != 1)
    throw new ArgumentException("Catalog zone SOA requires exactly one record.");
if (!records[0].Name.Equals(catalogZone.Name, StringComparison.OrdinalIgnoreCase))
    throw new ArgumentException($"SOA record name '{records[0].Name}' must match catalog zone name '{catalogZone.Name}'.");
catalogZone.SetRecords(DnsResourceRecordType.SOA, records);

Type guard

static bool IsValidCatalogSoa(IReadOnlyList<DnsResourceRecord> records, string zoneName)
    => records.Count == 1
    && records[0].Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase)
    && records[0].RDATA is DnsSOARecordData;

Prevention

When it happens

Trigger: Calling SetRecords(DnsResourceRecordType.SOA, records) on a CatalogZone where records has zero, two, or more entries, or where the record's Name property doesn't equal the catalog zone name. Also fires if the RDATA is not castable to DnsSOARecordData (would NPE on the cast, but the count/name check fires first).

Common situations: Zone transfer logic importing SOA records from a primary catalog server where the record name doesn't match; sending an empty or multi-record SOA list; programmatically building SOA records with the wrong owner name; BIND-style zone files where SOA name differs.

Related errors


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