{"record":{"id":"92c2e7f3b8d3dfe0","repo":"TechnitiumSoftware/DnsServer","slug":"cannot-set-records-please-try-again-92c2e7","errorCode":null,"errorMessage":"Cannot set records. Please try again.","messagePattern":"Cannot set records\\. Please try again\\.","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/Zones/PrimarySubDomainZone.cs","lineNumber":97,"sourceCode":"                case DnsResourceRecordType.SOA:\n                    throw new InvalidOperationException(\"Cannot set SOA record on sub domain.\");\n\n                case DnsResourceRecordType.DNSKEY:\n                case DnsResourceRecordType.RRSIG:\n                case DnsResourceRecordType.NSEC:\n                case DnsResourceRecordType.NSEC3PARAM:\n                case DnsResourceRecordType.NSEC3:\n                    throw new InvalidOperationException(\"Cannot set DNSSEC records.\");\n\n                case DnsResourceRecordType.FWD:\n                    throw new DnsServerException(\"The record type is not supported by primary zones.\");\n\n                default:\n                    if (records[0].OriginalTtlValue > _primaryZone.GetZoneSoaExpire())\n                        throw new DnsServerException(\"Cannot set records: TTL cannot be greater than SOA EXPIRE.\");\n\n                    if (!TrySetRecords(type, records, out IReadOnlyList<DnsResourceRecord> deletedRecords))\n                        throw new DnsServerException(\"Cannot set records. Please try again.\");\n\n                    _primaryZone.CommitAndIncrementSerial(deletedRecords, records);\n\n                    if (_primaryZone.DnssecStatus != AuthZoneDnssecStatus.Unsigned)\n                        _primaryZone.UpdateDnssecRecordsFor(this, type);\n\n                    _primaryZone.TriggerNotify();\n                    break;\n            }\n        }\n\n        public override bool AddRecord(DnsResourceRecord record)\n        {\n            if (_primaryZone.DnssecStatus != AuthZoneDnssecStatus.Unsigned)\n            {\n                switch (record.Type)\n                {\n                    case DnsResourceRecordType.ANAME:","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/Zones/PrimarySubDomainZone.cs#L79-L115","documentation":"Thrown by PrimarySubDomainZone.SetRecords() when TrySetRecords(type, records, out deletedRecords) returns false. TrySetRecords performs the actual atomic swap into the per-type _entries store; a false return indicates the operation could not be applied (typically a concurrency/contention failure on the underlying store, since a type/value mismatch would have been caught earlier). The message 'Please try again' signals a transient retry-eligible condition. DnsServerException, catchable.","triggerScenarios":"subZone.SetRecords(type, records) losing a compare-exchange / lock race inside TrySetRecords — most often under concurrent writers (parallel imports, simultaneous API calls, zone replication + edit at once).","commonSituations":"Bulk import with high parallelism; two admin sessions editing the same zone; replication/notify firing while a SetRecords is in flight.","solutions":["Retry the SetRecords call after a short backoff (the message explicitly invites retry).","Serialize writes to a given zone (one writer at a time) to avoid the contention that causes TrySetRecords to fail.","If it persists, re-query the zone state and rebuild the record set before retrying, in case the conflict changed the stored data."],"exampleFix":"// before\nsubZone.SetRecords(type, records);\n\n// after\nfor (int attempt = 0; ; attempt++)\n{\n    try { subZone.SetRecords(type, records); break; }\n    catch (DnsServerException ex) when (ex.Message.Contains(\"Please try again\") && attempt < 5)\n    {\n        System.Threading.Thread.Sleep(100 * (attempt + 1));\n    }\n}","handlingStrategy":"retry","validationCode":"// No pure-validation guard exists; this is a transient TrySetRecords failure.\n// Pre-check writer contention: avoid concurrent SetRecords on the same zone.\nusing (await _zoneWriteLock.LockAsync())\n    zone.SetRecords(type, records);","typeGuard":null,"tryCatchPattern":"for (int i = 0; i < 5; i++)\n{\n    try { zone.SetRecords(type, records); return; }\n    catch (DnsServerException ex) when (ex.Message.Contains(\"Please try again\")) { await System.Threading.Tasks.Task.Delay(100 * (i + 1)); }\n}","preventionTips":["Serialize writes per zone (lock or queue) so TrySetRecords does not contend.","Treat 'Please try again' as retry-eligible with bounded exponential backoff.","Limit import parallelism to one writer per zone."],"tags":["dns","primary-zone","subdomain","concurrency","retry","dnsserverexception"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}