{"record":{"id":"1a79e65176296b26","repo":"TechnitiumSoftware/DnsServer","slug":"invalid-axfr-response-was-received","errorCode":null,"errorMessage":"Invalid AXFR response was received.","messagePattern":"Invalid AXFR response was received\\.","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/ZoneManagers/AuthZoneManager.cs","lineNumber":2596,"sourceCode":"\n            //start incremental message\n            xfrRecords.Add(currentSoaRecord);\n\n            //write history\n            for (int i = index; i < zoneHistory.Count; i++)\n                xfrRecords.Add(zoneHistory[i]);\n\n            //end incremental message\n            xfrRecords.Add(currentSoaRecord);\n\n            //condense\n            return CondenseIncrementalZoneTransferRecords(zoneName, clientSoaRecord, xfrRecords);\n        }\n\n        public void SyncZoneTransferRecords(string zoneName, IReadOnlyList<DnsResourceRecord> xfrRecords)\n        {\n            if ((xfrRecords.Count < 2) || (xfrRecords[0].Type != DnsResourceRecordType.SOA) || !xfrRecords[0].Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase) || !xfrRecords[xfrRecords.Count - 1].Equals(xfrRecords[0]))\n                throw new DnsServerException(\"Invalid AXFR response was received.\");\n\n            List<DnsResourceRecord> latestRecords = new List<DnsResourceRecord>(xfrRecords.Count);\n            List<DnsResourceRecord> allGlueRecords = new List<DnsResourceRecord>(4);\n\n            if (zoneName.Length == 0)\n            {\n                //root zone case\n                for (int i = 1; i < xfrRecords.Count; i++)\n                {\n                    DnsResourceRecord record = xfrRecords[i];\n\n                    switch (record.Type)\n                    {\n                        case DnsResourceRecordType.A:\n                        case DnsResourceRecordType.AAAA:\n                            if (!allGlueRecords.Contains(record))\n                                allGlueRecords.Add(record);\n","sourceCodeStart":2578,"sourceCodeEnd":2614,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/ZoneManagers/AuthZoneManager.cs#L2578-L2614","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nauthZoneManager.SyncZoneTransferRecords(zoneName, xfrRecords);\n\n// after\nif (xfrRecords.Count < 2\n    || xfrRecords[0].Type != DnsResourceRecordType.SOA\n    || !xfrRecords[0].Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase)\n    || !xfrRecords[^1].Equals(xfrRecords[0]))\n{\n    _logger.LogError(\"Invalid AXFR response for zone '{Zone}'; re-requesting.\", zoneName);\n    xfrRecords = await dnsClient.QueryZoneTransferAsync(zoneName); // retry\n}\nauthZoneManager.SyncZoneTransferRecords(zoneName, xfrRecords);","handlingStrategy":"validation","validationCode":"static bool IsValidAxfrResponse(string zoneName, IReadOnlyList<DnsResourceRecord> xfrRecords)\n{\n    return xfrRecords.Count >= 2\n        && xfrRecords[0].Type == DnsResourceRecordType.SOA\n        && xfrRecords[0].Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase)\n        && xfrRecords[^1].Equals(xfrRecords[0]);\n}\n\nif (!IsValidAxfrResponse(zoneName, xfrRecords))\n    throw new InvalidOperationException(\"Invalid AXFR response structure.\");","typeGuard":"static bool IsValidAxfrEnvelope(IReadOnlyList<DnsResourceRecord> records, string zoneName)\n    => records.Count >= 2\n       && records[0].Type == DnsResourceRecordType.SOA\n       && records[0].Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase)\n       && records[^1].Equals(records[0]);","tryCatchPattern":"try\n{\n    authZoneManager.SyncZoneTransferRecords(zoneName, xfrRecords);\n}\ncatch (DnsServerException ex) when (ex.Message.Contains(\"Invalid AXFR response\"))\n{\n    logger.LogError(\"AXFR sync failed for '{Zone}'; response malformed. Retrying.\", zoneName);\n    xfrRecords = await dnsClient.QueryZoneTransferAsync(zoneName);\n    authZoneManager.SyncZoneTransferRecords(zoneName, xfrRecords);\n}","preventionTips":["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."],"tags":["zone-transfer","axfr","zone-management","validation","network"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}