{"record":{"id":"3c159f697706b3b5","repo":"TechnitiumSoftware/DnsServer","slug":"cannot-set-record-soa-retry-cannot-be-greater-tha-3c159f","errorCode":null,"errorMessage":"Cannot set record: SOA RETRY cannot be greater than SOA REFRESH.","messagePattern":"Cannot set record: SOA RETRY cannot be greater than SOA REFRESH\\.","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/Zones/PrimaryZone.cs","lineNumber":2546,"sourceCode":"\n            switch (type)\n            {\n                case DnsResourceRecordType.CNAME:\n                case DnsResourceRecordType.DS:\n                    throw new InvalidOperationException(\"Cannot set \" + type.ToString() + \" record at zone apex.\");\n\n                case DnsResourceRecordType.SOA:\n                    if ((records.Count != 1) || !records[0].Name.Equals(_name, StringComparison.OrdinalIgnoreCase))\n                        throw new InvalidOperationException(\"Invalid SOA record.\");\n\n                    DnsResourceRecord newSoaRecord = records[0];\n                    DnsSOARecordData newSoa = newSoaRecord.RDATA as DnsSOARecordData;\n\n                    if (newSoaRecord.OriginalTtlValue > newSoa.Expire)\n                        throw new DnsServerException(\"Cannot set record: TTL cannot be greater than SOA EXPIRE.\");\n\n                    if (newSoa.Retry > newSoa.Refresh)\n                        throw new DnsServerException(\"Cannot set record: SOA RETRY cannot be greater than SOA REFRESH.\");\n\n                    if (newSoa.Refresh > newSoa.Expire)\n                        throw new DnsServerException(\"Cannot set record: SOA REFRESH cannot be greater than SOA EXPIRE.\");\n\n                    //remove any record info except serial date scheme and comments\n                    bool useSoaSerialDateScheme;\n                    string comments;\n                    {\n                        SOARecordInfo recordInfo = newSoaRecord.GetAuthSOARecordInfo();\n\n                        useSoaSerialDateScheme = recordInfo.UseSoaSerialDateScheme;\n                        comments = recordInfo.Comments;\n                    }\n\n                    newSoaRecord.Tag = null; //remove old record info\n\n                    {\n                        SOARecordInfo recordInfo = newSoaRecord.GetAuthSOARecordInfo();","sourceCodeStart":2528,"sourceCodeEnd":2564,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/Zones/PrimaryZone.cs#L2528-L2564","documentation":"Thrown by PrimaryZone.SetRecords() in the SOA case when newSoa.Retry > newSoa.Refresh. RETRY is the interval a secondary waits before retrying a failed refresh; it must not exceed REFRESH, otherwise the retry schedule is inconsistent with the refresh schedule. The server rejects this invariant.","triggerScenarios":"Calling SetRecords with an SOA whose Retry value is greater than its Refresh value (e.g. Refresh 3600, Retry 9000).","commonSituations":"Manually editing SOA timers and swapping RETRY/REFRESH; importing a zone with malformed timers; defaults from a template where RETRY was raised without raising REFRESH.","solutions":["Set RETRY <= REFRESH on the SOA before calling SetRecords.","If a longer RETRY is genuinely needed, raise REFRESH to at least that value first.","Validate Retry <= Refresh when constructing the SOA."],"exampleFix":"// before\nvar soa = new DnsSOARecordData { Refresh = 3600, Retry = 9000 };\nzone.SetRecords(DnsResourceRecordType.SOA, new[] { BuildSoaRecord(ttl, soa) }); // throws\n\n// after\nvar soa = new DnsSOARecordData { Refresh = 9000, Retry = 3600 };\nzone.SetRecords(DnsResourceRecordType.SOA, new[] { BuildSoaRecord(ttl, soa) });","handlingStrategy":"validation","validationCode":"if (type == DnsResourceRecordType.SOA)\n{\n    var soa = (DnsSOARecordData)records[0].RDATA;\n    if (soa.Retry > soa.Refresh)\n        throw new ArgumentException(\"SOA RETRY must be <= SOA REFRESH.\");\n}\n\nzone.SetRecords(type, records);","typeGuard":"static bool SoaRetryWithinRefresh(DnsResourceRecord soaRecord)\n{\n    var soa = (DnsSOARecordData)soaRecord.RDATA;\n    return soa.Retry <= soa.Refresh;\n}","tryCatchPattern":"try { zone.SetRecords(type, records); }\ncatch (DnsServerException ex) when (ex.Message.Contains(\"SOA RETRY cannot be greater than SOA REFRESH\"))\n{ Log.Error(\"Set SOA RETRY <= SOA REFRESH.\"); }","preventionTips":["Keep RETRY <= REFRESH in SOA templates.","Double-check timer pairs when hand-editing SOA values.","Validate SOA timers in a shared helper before any SOA write."],"tags":["dns","record","soa","refresh","retry","validation"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}