{"record":{"id":"353dc8a87b5af610","repo":"TechnitiumSoftware/DnsServer","slug":"dns-server-cluster-config-file-format-is-invalid","errorCode":null,"errorMessage":"DNS Server Cluster config file format is invalid.","messagePattern":"DNS Server Cluster config file format is invalid\\.","errorType":"exception","errorClass":"InvalidDataException","httpStatus":null,"severity":"critical","filePath":"DnsServerCore/Cluster/ClusterManager.cs","lineNumber":363,"sourceCode":"                    }\n                }\n                catch (Exception ex)\n                {\n                    _dnsWebService.LogManager.Write(\"DNS Server encountered an error while deleting the Cluster config file: \" + configFile, ex);\n                }\n\n                if (_pendingSave)\n                {\n                    _pendingSave = false;\n                    _saveTimer.Change(Timeout.Infinite, Timeout.Infinite);\n                }\n            }\n        }\n\n        private void ReadConfigFrom(Stream s)\n        {\n            if (Encoding.ASCII.GetString(s.ReadExactly(2)) != \"CL\") //format\n                throw new InvalidDataException(\"DNS Server Cluster config file format is invalid.\");\n\n            BinaryReader bR = new BinaryReader(s);\n\n            int version = bR.ReadByte();\n            switch (version)\n            {\n                case 1:\n                    _clusterDomain = bR.ReadString();\n                    _heartbeatRefreshIntervalSeconds = bR.ReadUInt16();\n                    _heartbeatRetryIntervalSeconds = bR.ReadUInt16();\n                    _configRefreshIntervalSeconds = bR.ReadUInt16();\n                    _configRetryIntervalSeconds = bR.ReadUInt16();\n                    _configLastSynced = s.ReadDateTime();\n\n                    Dictionary<int, ClusterNode> clusterNodes = null;\n                    int count = bR.ReadByte();\n\n                    if (count > 0)","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Cluster/ClusterManager.cs#L345-L381","documentation":"Thrown by ClusterManager.ReadConfigFrom(Stream) when the first two bytes of the stream are not the ASCII magic 'CL'. This is a file-format integrity check: every valid cluster config starts with 'CL'. A mismatch means the file is not a cluster config at all, is truncated, or is corrupt. ReadExactly(2) will itself throw if fewer than 2 bytes are available.","triggerScenarios":"Pointing the cluster config loader at a file that is empty, truncated, from a different feature, or otherwise missing the 'CL' header — e.g. a stale/partial save, a wrong file path, or a file replaced by an unrelated config.","commonSituations":"Config file half-written due to a crash during save; the path was misconfigured to point at a non-cluster config; disk/filesystem corruption; an interrupted copy leaving a zero-byte file.","solutions":["Restore the cluster config file from a known-good backup.","Delete the corrupt config so the cluster can be re-initialized from scratch.","Add a pre-check that reads the first two bytes and verifies 'CL' before invoking ReadConfigFrom."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    clusterManager.Load();\n}\ncatch (InvalidDataException ex) when (ex.Message.Contains(\"Cluster config file format is invalid\"))\n{\n    logger.LogCritical(ex, \"Cluster config is corrupt; restoring from backup or re-initializing.\");\n    RestoreClusterConfigFromBackup();\n}","preventionTips":["Keep backups of the cluster config file.","Use atomic writes (temp file + rename) for config saves to avoid truncation.","Verify the 'CL' header before handing the stream to ReadConfigFrom."],"tags":["cluster","config","serialization","corruption","file-format","technitium-dns-server"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}