TechnitiumSoftware/DnsServer · error · DnsServerException
Invalid AXFR response was received.
Error message
Invalid AXFR response was received.
What it means
Thrown by SyncZoneTransferRecords when the received AXFR response fails structural validation: fewer than 2 records, first record is not SOA, first record name does not match zoneName, or first and last records are not equal (SOA bracketing). This is the response-side parser for incoming zone transfers from a remote primary.
Source
Thrown at DnsServerCore/Dns/ZoneManagers/AuthZoneManager.cs:2596
//start incremental message
xfrRecords.Add(currentSoaRecord);
//write history
for (int i = index; i < zoneHistory.Count; i++)
xfrRecords.Add(zoneHistory[i]);
//end incremental message
xfrRecords.Add(currentSoaRecord);
//condense
return CondenseIncrementalZoneTransferRecords(zoneName, clientSoaRecord, xfrRecords);
}
public void SyncZoneTransferRecords(string zoneName, IReadOnlyList<DnsResourceRecord> xfrRecords)
{
if ((xfrRecords.Count < 2) || (xfrRecords[0].Type != DnsResourceRecordType.SOA) || !xfrRecords[0].Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase) || !xfrRecords[xfrRecords.Count - 1].Equals(xfrRecords[0]))
throw new DnsServerException("Invalid AXFR response was received.");
List<DnsResourceRecord> latestRecords = new List<DnsResourceRecord>(xfrRecords.Count);
List<DnsResourceRecord> allGlueRecords = new List<DnsResourceRecord>(4);
if (zoneName.Length == 0)
{
//root zone case
for (int i = 1; i < xfrRecords.Count; i++)
{
DnsResourceRecord record = xfrRecords[i];
switch (record.Type)
{
case DnsResourceRecordType.A:
case DnsResourceRecordType.AAAA:
if (!allGlueRecords.Contains(record))
allGlueRecords.Add(record);
View on GitHub (pinned to d0484b6c1e)
Solutions
- Validate the xfrRecords structure before calling SyncZoneTransferRecords: check count >= 2, first and last are SOA, first.Name == zoneName, and first.Equals(last).
- Re-request the full zone transfer from the primary if the response is malformed.
- Verify the primary server's zone name matches the secondary's configured zone name.
- Check network connectivity and TCP buffer sizes for large zone transfers.
Example fix
// before
authZoneManager.SyncZoneTransferRecords(zoneName, xfrRecords);
// after
if (xfrRecords.Count < 2
|| xfrRecords[0].Type != DnsResourceRecordType.SOA
|| !xfrRecords[0].Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase)
|| !xfrRecords[^1].Equals(xfrRecords[0]))
{
_logger.LogError("Invalid AXFR response for zone '{Zone}'; re-requesting.", zoneName);
xfrRecords = await dnsClient.QueryZoneTransferAsync(zoneName); // retry
}
authZoneManager.SyncZoneTransferRecords(zoneName, xfrRecords); Defensive patterns
Strategy: validation
Validate before calling
static bool IsValidAxfrResponse(string zoneName, IReadOnlyList<DnsResourceRecord> xfrRecords)
{
return xfrRecords.Count >= 2
&& xfrRecords[0].Type == DnsResourceRecordType.SOA
&& xfrRecords[0].Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase)
&& xfrRecords[^1].Equals(xfrRecords[0]);
}
if (!IsValidAxfrResponse(zoneName, xfrRecords))
throw new InvalidOperationException("Invalid AXFR response structure."); Type guard
static bool IsValidAxfrEnvelope(IReadOnlyList<DnsResourceRecord> records, string zoneName)
=> records.Count >= 2
&& records[0].Type == DnsResourceRecordType.SOA
&& records[0].Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase)
&& records[^1].Equals(records[0]); Try / catch
try
{
authZoneManager.SyncZoneTransferRecords(zoneName, xfrRecords);
}
catch (DnsServerException ex) when (ex.Message.Contains("Invalid AXFR response"))
{
logger.LogError("AXFR sync failed for '{Zone}'; response malformed. Retrying.", zoneName);
xfrRecords = await dnsClient.QueryZoneTransferAsync(zoneName);
authZoneManager.SyncZoneTransferRecords(zoneName, xfrRecords);
} Prevention
- Validate the AXFR envelope (SOA bracketing, count >= 2, name match) before calling SyncZoneTransferRecords.
- Re-request the zone transfer from the primary if the response is malformed.
- Check TCP connectivity and buffer sizes for large zone transfers.
- Verify the primary server's zone name matches the secondary's configuration.
When it happens
Trigger: Calling SyncZoneTransferRecords(zoneName, xfrRecords) with malformed xfrRecords: truncated transfer (count < 2), missing SOA header/footer, SOA name mismatch (wrong zone data received), or start/end SOA records that differ (incomplete or corrupted transfer). This processes data received from a remote server.
Common situations: Remote primary server is misbehaving (truncated response, wrong zone data); network corruption or TCP truncation of the transfer stream; zone name mismatch between secondary config and primary's actual zone; AXFR response from a non-standard DNS server that doesn't bracket with SOA.
Related errors
- Invalid IXFR/AXFR response was received.
- Zone was not found: {zoneName}
- Zone must be a primary, secondary, or forwarder zone.
- No SOA record was found for IXFR.
- No such zone was found: {zoneName}
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/1a79e65176296b26.
Report an issue: GitHub.