{"record":{"id":"fba6ff44c8b3cc18","repo":"TechnitiumSoftware/DnsServer","slug":"cannot-update-record-disabling-records-in-a-signe","errorCode":null,"errorMessage":"Cannot update record: disabling records in a signed zones is not supported.","messagePattern":"Cannot update record: disabling records in a signed zones is not supported\\.","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/Zones/PrimarySubDomainZone.cs","lineNumber":236,"sourceCode":"        {\n            switch (oldRecord.Type)\n            {\n                case DnsResourceRecordType.SOA:\n                    throw new InvalidOperationException(\"Cannot update record: use SetRecords() for \" + oldRecord.Type.ToString() + \" record.\");\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 update DNSSEC records.\");\n\n                default:\n                    if (oldRecord.Type != newRecord.Type)\n                        throw new InvalidOperationException(\"Old and new record types do not match.\");\n\n                    if ((_primaryZone.DnssecStatus != AuthZoneDnssecStatus.Unsigned) && newRecord.GetAuthGenericRecordInfo().Disabled)\n                        throw new DnsServerException(\"Cannot update record: disabling records in a signed zones is not supported.\");\n\n                    if (newRecord.OriginalTtlValue > _primaryZone.GetZoneSoaExpire())\n                        throw new DnsServerException(\"Cannot update record: TTL cannot be greater than SOA EXPIRE.\");\n\n                    if (!TryDeleteRecord(oldRecord.Type, oldRecord.RDATA, out DnsResourceRecord deletedRecord))\n                        throw new InvalidOperationException(\"Cannot update record: the record does not exists to be updated.\");\n\n                    AddRecord(newRecord, out IReadOnlyList<DnsResourceRecord> addedRecords, out IReadOnlyList<DnsResourceRecord> deletedRecords);\n\n                    List<DnsResourceRecord> allDeletedRecords = new List<DnsResourceRecord>(deletedRecords.Count + 1);\n                    allDeletedRecords.Add(deletedRecord);\n                    allDeletedRecords.AddRange(deletedRecords);\n\n                    _primaryZone.CommitAndIncrementSerial(allDeletedRecords, addedRecords);\n\n                    if (_primaryZone.DnssecStatus != AuthZoneDnssecStatus.Unsigned)\n                        _primaryZone.UpdateDnssecRecordsFor(this, oldRecord.Type);\n","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/Zones/PrimarySubDomainZone.cs#L218-L254","documentation":"Thrown by PrimarySubDomainZone.UpdateRecord when the zone is DNSSEC-signed (_primaryZone.DnssecStatus != Unsigned) AND the new record has its AuthGenericRecordInfo.Disabled flag set. Disabling (RFC 4041) a record changes the RRset that must be signed; this implementation does not support disabling records in a signed zone, so it raises DnsServerException before applying the update. (Message text 'zones' is a verbatim source typo.)","triggerScenarios":"zone.UpdateRecord(old, new) where newRecord.GetAuthGenericRecordInfo().Disabled is true and the zone is signed (SignedWithNSEC or SignedWithNSEC3).","commonSituations":"Temporarily disabling a record for maintenance while DNSSEC is enabled; importing records that carry a 'disabled' flag into a signed zone.","solutions":["Do not set Disabled=true on records in a signed zone; delete the record instead.","Unsign the zone first if disabling is mandatory, then re-sign.","Clear the Disabled flag on newRecord before updating."],"exampleFix":"// before\nnewRecord.GetAuthGenericRecordInfo().Disabled = true;\nzone.UpdateRecord(old, newRecord); // signed zone\n\n// after\nnewRecord.GetAuthGenericRecordInfo().Disabled = false;\nzone.UpdateRecord(old, newRecord);","handlingStrategy":"validation","validationCode":"bool signed = primaryZone.DnssecStatus != AuthZoneDnssecStatus.Unsigned;\nif (signed && newRecord.GetAuthGenericRecordInfo().Disabled)\n    newRecord.GetAuthGenericRecordInfo().Disabled = false; // or unsign first\nzone.UpdateRecord(oldRecord, newRecord);","typeGuard":"static bool IsDisabledAllowed(AuthZoneDnssecStatus status, DnsResourceRecord r) =>\n    status == AuthZoneDnssecStatus.Unsigned || !r.GetAuthGenericRecordInfo().Disabled;","tryCatchPattern":null,"preventionTips":["Do not disable records in a signed zone; delete them instead.","Clear Disabled before update, or unsign/re-sign around it.","Surface the signed-zone limitation to UI/API callers."],"tags":["csharp","dns","dnssec","zone-management","validation","technitium-dns"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}