{"record":{"id":"604e6f179d8b6186","repo":"TechnitiumSoftware/DnsServer","slug":"cannot-add-record-ttl-cannot-be-greater-than-soa-604e6f","errorCode":null,"errorMessage":"Cannot add record: TTL cannot be greater than SOA EXPIRE.","messagePattern":"Cannot add record: TTL cannot be greater than SOA EXPIRE\\.","errorType":"exception","errorClass":"DnsServerException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/Dns/Zones/PrimarySubDomainZone.cs","lineNumber":141,"sourceCode":"                        break;\n                }\n            }\n\n            switch (record.Type)\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 add DNSSEC record.\");\n\n                case DnsResourceRecordType.FWD:\n                    throw new DnsServerException(\"The record type is not supported by primary zones.\");\n\n                default:\n                    if (record.OriginalTtlValue > _primaryZone.GetZoneSoaExpire())\n                        throw new DnsServerException(\"Cannot add record: TTL cannot be greater than SOA EXPIRE.\");\n\n                    AddRecord(record, out IReadOnlyList<DnsResourceRecord> addedRecords, out IReadOnlyList<DnsResourceRecord> deletedRecords);\n\n                    if (addedRecords.Count > 0)\n                    {\n                        _primaryZone.CommitAndIncrementSerial(deletedRecords, addedRecords);\n\n                        if (_primaryZone.DnssecStatus != AuthZoneDnssecStatus.Unsigned)\n                            _primaryZone.UpdateDnssecRecordsFor(this, record.Type);\n\n                        _primaryZone.TriggerNotify();\n\n                        return true;\n                    }\n\n                    return false;\n            }\n        }","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Dns/Zones/PrimarySubDomainZone.cs#L123-L159","documentation":"Thrown by PrimarySubDomainZone.AddRecord when the new record's OriginalTtlValue is greater than the parent zone's SOA EXPIRE value. DNSSEC and secondary-refresh correctness require a record TTL to fit within the SOA EXPIRE; a TTL longer than EXPIRE would let caches outlive secondary validity windows. The check uses _primaryZone.GetZoneSoaExpire() and fires a DnsServerException before the record is committed or the serial incremented.","triggerScenarios":"zone.AddRecord(record) where record.OriginalTtlValue > _primaryZone.GetZoneSoaExpire(). Typical when importing a record with a long TTL (e.g., 86400+) into a zone whose SOA EXPIRE is set low.","commonSituations":"Lowered SOA EXPIRE during testing; bulk import of records exported from a zone with a much larger EXPIRE; misconfigured SOA default template.","solutions":["Lower the record TTL to be <= the zone SOA EXPIRE before adding.","Raise the zone SOA EXPIRE (via SetRecords on the SOA RRset) to accommodate the desired TTL, then add the record.","If importing many records, clamp/normalize their TTLs to the zone EXPIRE first."],"exampleFix":"// before\nzone.AddRecord(record); // record.OriginalTtlValue = 86400, SOA EXPIRE = 3600\n\n// after\nuint expire = zone.GetZoneSoaExpire();\nif (record.OriginalTtlValue > expire)\n    record = record.WithTtl(Math.Min(record.OriginalTtlValue, expire));\nzone.AddRecord(record);","handlingStrategy":"validation","validationCode":"uint expire = primaryZone.GetZoneSoaExpire();\nif (record.OriginalTtlValue > expire)\n    record = record.WithTtl(expire); // or reject","typeGuard":"static bool TtlFitsSoaExpire(DnsResourceRecord r, uint soaExpire) => r.OriginalTtlValue <= soaExpire;","tryCatchPattern":null,"preventionTips":["Read the zone SOA EXPIRE once and clamp all record TTLs against it before add/update.","Keep SOA EXPIRE >= your largest acceptable record TTL.","Validate TTLs in import pipelines against the destination zone's SOA."],"tags":["csharp","dns","ttl","soa","validation","technitium-dns"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}