{"record":{"id":"b4c8ae08d3cc218e","repo":"TechnitiumSoftware/DnsServer","slug":"dns-server-config-version-not-supported-b4c8ae","errorCode":null,"errorMessage":"DNS Server config version not supported.","messagePattern":"DNS Server config version not supported\\.","errorType":"exception","errorClass":"InvalidDataException","httpStatus":null,"severity":"error","filePath":"DnsServerCore/DnsWebServiceLegacy.cs","lineNumber":151,"sourceCode":"                            new NetworkAccessControl(IPAddress.Parse(\"192.168.0.0\"), 16),\n                            new NetworkAccessControl(IPAddress.Parse(\"2000::\"), 3, true),\n                            new NetworkAccessControl(IPAddress.IPv6Any, 0)\n                        ];\n                }\n\n                _dnsServer.BlockingBypassList = null;\n                _dnsServer.BlockingAnswerTtl = 30;\n                _dnsServer.ResolverConcurrency = 2;\n                _dnsServer.CacheZoneManager.ServeStaleAnswerTtl = CacheZoneManager.SERVE_STALE_ANSWER_TTL;\n                _dnsServer.CacheZoneManager.ServeStaleResetTtl = CacheZoneManager.SERVE_STALE_RESET_TTL;\n                _dnsServer.ServeStaleMaxWaitTime = DnsServer.SERVE_STALE_MAX_WAIT_TIME;\n                _dnsServer.ConcurrentForwarding = true;\n                _dnsServer.ResolverLogManager = _log;\n                _dnsServer.StatsManager.EnableInMemoryStats = false;\n            }\n            else\n            {\n                throw new InvalidDataException(\"DNS Server config version not supported.\");\n            }\n        }\n\n        private void ReadConfigFromV42(BinaryReader bR, int version)\n        {\n            //web service\n            {\n                _webServiceHttpPort = bR.ReadInt32();\n                _webServiceTlsPort = bR.ReadInt32();\n\n                {\n                    int count = bR.ReadByte();\n                    if (count > 0)\n                    {\n                        IPAddress[] localAddresses = new IPAddress[count];\n\n                        for (int i = 0; i < count; i++)\n                            localAddresses[i] = IPAddressExtensions.ReadFrom(bR);","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/DnsWebServiceLegacy.cs#L133-L169","documentation":"Thrown by DnsWebService.ReadOldConfigFrom() when the legacy binary 'dns.config' file passes the 'DS' magic-byte check but its 1-byte version field falls outside every supported range (currently only version 2-27 and 28-42 are implemented, dispatched to ReadConfigFromV27/ReadConfigFromV42). It is an InvalidDataException (System.IO), signaling that the on-disk config format predates or postdates this build's migration code. The version byte is read via ReadByte() (0-255), so versions 0, 1, and 43-and-above all land in the else branch.","triggerScenarios":"A dns.config file written by a DNS Server build newer than this binary (version byte >= 43) being opened by an older build — the classic downgrade case. Also: a config from the earliest releases (version 0 or 1, pre-v2), a truncated/corrupted file whose version byte is garbage, or a file that shares the 'DS' header but belongs to a different Technitium product. Through TryLoadOldConfigFile() the exception is caught and logged (returns false), but through TryLoadOldConfigFrom(Stream) or a direct call to ReadOldConfigFrom it propagates to the caller.","commonSituations":"Rolling back the DNS server binary to an older release while keeping the newer config directory; copying a config folder between machines running mismatched server versions; a half-written dns.config left by a crash mid-save; pointing two different server versions at the same config folder (e.g. a migration dry-run).","solutions":["Upgrade the DNS Server binary to a version equal to or newer than the one that wrote the config (version 43+ files need a 43+-capable build). The forward direction always supports prior versions.","If you must downgrade: move the existing dns.config aside (rename to dns.config.bak) so the server regenerates a fresh v-appropriate config on next start, then re-apply your settings through the web UI/API.","Restore dns.config from a backup taken under a server version this binary supports (<= the version this build's ReadOldConfigFrom can parse).","Verify file integrity: confirm the file starts with 'DS', is not zero-length/truncated, and that the third byte (version) is within 2-42. A corrupt file should be discarded, not force-loaded."],"exampleFix":"// before: older binary opens newer config\nusing var fs = File.OpenRead(configPath);\nwebService.TryLoadOldConfigFrom(fs); // throws InvalidDataException \"config version not supported\"\n\n// after: let the binary write a fresh config for its own version\nif (File.Exists(configPath)) File.Move(configPath, configPath + \".bak\");\nwebService.LoadConfigFile(); // regenerates dns.config at the binary's native version","handlingStrategy":"validation","validationCode":"// Validate the legacy config before handing it to the parser.\n// Supported: 'DS' magic + version byte in [2,42] (2-27 -> V27 reader, 28-42 -> V42 reader).\nstatic bool IsLegacyConfigSupported(string path)\n{\n    if (!File.Exists(path)) return false;\n    using var fs = File.OpenRead(path);\n    Span<byte> hdr = stackalloc byte[3];\n    if (fs.Read(hdr) < 3) return false;\n    if (hdr[0] != (byte)'D' || hdr[1] != (byte)'S') return false;\n    int version = hdr[2];\n    return version is >= 2 and <= 42;\n}\n\n// Usage before load:\nstring cfg = Path.Combine(configFolder, \"dns.config\");\nif (File.Exists(cfg) && !IsLegacyConfigSupported(cfg))\n    File.Move(cfg, cfg + \".bak\"); // let the server regenerate a supported config","typeGuard":"// Narrows a raw byte stream to a known-supported legacy config version.\nstatic bool TryReadSupportedLegacyVersion(BinaryReader bR, out int version)\n{\n    version = -1;\n    if (bR.BaseStream.Length < 3) return false;\n    if (bR.ReadByte() != (byte)'D' || bR.ReadByte() != (byte)'S') return false;\n    int v = bR.ReadByte();\n    if (v is >= 2 and <= 42) { version = v; return true; }\n    return false;\n}","tryCatchPattern":"try\n{\n    webService.TryLoadOldConfigFrom(stream);\n}\ncatch (InvalidDataException ex) when (ex.Message.Contains(\"config version not supported\"))\n{\n    // The config is from a newer/older build than this binary can migrate.\n    // Back it up and let the server emit a fresh config; do NOT retry with the same bytes.\n    log.Warn($\"Unsupported legacy config version; regenerating config. Reason: {ex.Message}\");\n    File.Move(configPath, configPath + \".bak\", overwrite: true);\n    webService.LoadConfigFile();\n}","preventionTips":["Never downgrade the DNS Server binary across a config-format boundary without first backing up and removing the newer dns.config; forward upgrades migrate old configs, reverse downgrades do not.","Pin the server version in deployment (container tag / package version) so a config folder is always read by a compatible build.","After any successful start, keep a versioned backup of dns.config so a bad migration can be rolled back to a supported version rather than hand-edited.","Validate the 'DS' header + version byte (range 2-42) before attempting a programmatic load — it is a one-line guard that prevents the throw entirely.","Treat a config that fails this check as suspect, not just 'old': a truncated or cross-product file can also land in the unsupported branch."],"tags":["dns-server","technitium","config","migration","version-mismatch","csharp"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}