{"record":{"id":"92bb095975522636","repo":"TechnitiumSoftware/DnsServer","slug":"dns-server-auth-config-file-format-is-invalid","errorCode":null,"errorMessage":"DNS Server auth config file format is invalid.","messagePattern":"DNS Server auth config file format is invalid\\.","errorType":"exception","errorClass":"InvalidDataException","httpStatus":null,"severity":"critical","filePath":"DnsServerCore/Auth/AuthManager.cs","lineNumber":387,"sourceCode":"                if (immediately)\n                {\n                    SaveConfigFileInternal();\n                    _pendingSave = false;\n                    return;\n                }\n\n                if (_pendingSave)\n                    return;\n\n                _pendingSave = true;\n                _saveTimer.Change(SAVE_TIMER_INITIAL_INTERVAL, Timeout.Infinite);\n            }\n        }\n\n        private void ReadConfigFrom(Stream s, bool isConfigTransfer, out bool restartWebService)\n        {\n            if (Encoding.ASCII.GetString(s.ReadExactly(2)) != \"AS\") //format\n                throw new InvalidDataException(\"DNS Server auth config file format is invalid.\");\n\n            restartWebService = false;\n\n            ConcurrentDictionary<string, Group> groups = new ConcurrentDictionary<string, Group>(1, 4);\n            ConcurrentDictionary<string, User> users = new ConcurrentDictionary<string, User>(1, 4);\n            ConcurrentDictionary<PermissionSection, Permission> permissions = new ConcurrentDictionary<PermissionSection, Permission>(1, 11);\n            ConcurrentDictionary<string, UserSession> sessions = new ConcurrentDictionary<string, UserSession>(1, 10);\n\n            BinaryReader bR = new BinaryReader(s);\n\n            int version = bR.ReadByte();\n            switch (version)\n            {\n                case 1:\n                case 2:\n                case 3:\n                    {\n                        int count = bR.ReadByte();","sourceCodeStart":369,"sourceCodeEnd":405,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore/Auth/AuthManager.cs#L369-L405","documentation":"Thrown as InvalidDataException while reading the auth config binary stream when the first two bytes are not the ASCII magic \"AS\". The auth.config file is a custom binary format, and this check guards the very first read before parsing users, groups, permissions, and sessions. It surfaces at server startup (LoadConfigFile), during admin reset (resetadmin.config), or during config transfer/backup restore, and it stops the server from booting on a corrupt or foreign file.","triggerScenarios":"Calling ReadConfigFrom on a stream whose first two bytes are not 0x41 0x53 ('AS'): an empty/truncated auth.config, a zero-byte file, a text file dropped into the config folder, or a restore that pulled in a non-auth file as auth.config.","commonSituations":"Config folder got corrupted by a crash mid-write or disk-full event; a backup restore pointed at the wrong archive entry; a manual edit of auth.config with a text editor destroyed the binary header; docker volume mount overwrote auth.config with a directory or empty bind-mount.","solutions":["Restore auth.config from a known-good backup or delete it so the server regenerates a fresh default config with the admin/admin account.","If using resetadmin.config, regenerate it via the official password-reset procedure instead of hand-crafting a file.","Verify the file is at least 2 bytes and starts with bytes 41 53 hex ('AS') before starting the server.","For backup restore, ensure the archive was produced by the same DNS Server version and that the auth.config entry is intact."],"exampleFix":"// before: corrupt/empty auth.config prevents startup\n// after: validate the header before attempting a load, or let the server recreate it\nusing var fs = File.OpenRead(authConfigPath);\nSpan<byte> hdr = stackalloc byte[2];\nif (await fs.ReadAsync(hdr) < 2 || hdr[0] != (byte)'A' || hdr[1] != (byte)'S')\n{\n    File.Delete(authConfigPath); // force regeneration of default config\n}","handlingStrategy":"try-catch","validationCode":"// Validate the auth.config header before letting the server load it\nbyte[] head = File.ReadAllBytes(authConfigPath).AsSpan(0, 2).ToArray();\nif (head.Length < 2 || head[0] != (byte)'A' || head[1] != (byte)'S')\n    throw new InvalidOperationException(\"auth.config is not a valid DNS Server auth config; header check failed.\");","typeGuard":"bool IsValidAuthConfigHeader(byte[] bytes) => bytes.Length >= 2 && bytes[0] == (byte)'A' && bytes[1] == (byte)'S';","tryCatchPattern":"try { StartServer(); }\ncatch (InvalidDataException ex) when (ex.Message.Contains(\"auth config file format is invalid\"))\n{\n    // restore from backup or delete auth.config to regenerate defaults\n    RestoreAuthConfigBackupOrReset();\n}","preventionTips":["Never edit auth.config with a text editor; it is binary.","Back up auth.config regularly and before upgrades.","Keep the config folder on reliable storage to avoid truncated writes."],"tags":["config","startup","binary-format","auth"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}