{"record":{"id":"4a960d2a63917a47","repo":"TechnitiumSoftware/DnsServer","slug":"cannot-update-dnssec-records","errorCode":null,"errorMessage":"Cannot update DNSSEC records.","messagePattern":"Cannot update DNSSEC records\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/Zones/PrimarySubDomainZone.cs","lineNumber":229,"sourceCode":"                    }\n\n                    return false;\n            }\n        }\n\n        public override void UpdateRecord(DnsResourceRecord oldRecord, DnsResourceRecord newRecord)\n        {\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);","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/Zones/PrimarySubDomainZone.cs#L211-L247","documentation":"Thrown by PrimarySubDomainZone.UpdateRecord when the record being updated is a DNSSEC type (DNSKEY/RRSIG/NSEC/NSEC3PARAM/NSEC3). DNSSEC RRs are derived from signing keys and cannot be updated through the generic record API without desynchronizing signatures. The guard raises InvalidOperationException early in the type switch.","triggerScenarios":"zone.UpdateRecord(oldRecord, newRecord) with oldRecord.Type one of DNSKEY, RRSIG, NSEC, NSEC3PARAM, NSEC3.","commonSituations":"Re-importing a zone export that includes RRSIG/DNSKEY lines into the generic updater; tooling unaware that signed zones own these RRs.","solutions":["Skip DNSSEC types in the update path; manage them via signing/key APIs.","Unsign and re-sign if the DNSSEC data is genuinely stale.","Re-export the zone without DNSSEC records before replaying edits."],"exampleFix":"// before\nzone.UpdateRecord(oldRrsig, newRrsig);\n\n// after\nif (!IsDnssecRecordType(oldRecord.Type))\n    zone.UpdateRecord(oldRecord, newRecord);","handlingStrategy":"validation","validationCode":"if (IsDnssecRecordType(oldRecord.Type)) return; // signer-managed\nzone.UpdateRecord(oldRecord, newRecord);","typeGuard":"static bool IsDnssecRecordType(DnsResourceRecordType t) =>\n    t == DnsResourceRecordType.DNSKEY || t == DnsResourceRecordType.RRSIG ||\n    t == DnsResourceRecordType.NSEC || t == DnsResourceRecordType.NSEC3PARAM ||\n    t == DnsResourceRecordType.NSEC3;","tryCatchPattern":null,"preventionTips":["Exclude DNSSEC types from generic update pipelines.","Strip RRSIG/DNSKEY/NSEC lines from zone exports before replaying edits.","Manage DNSSEC data only via sign/unsign/key-roll APIs."],"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"}