{"record":{"id":"29dbc4fdadbafba1","repo":"JosefNemec/Playnite","slug":"current-data-file-requires-password","errorCode":null,"errorMessage":"Current data file requires password","messagePattern":"Current data file requires password","errorType":"exception","errorClass":"LiteDB.LiteException","httpStatus":null,"severity":"critical","filePath":"source/Playnite/Database/Collections/LiteDBFileReaderV7.cs","lineNumber":612,"sourceCode":"    {\n        // v7 uses 4k page size\n        private const int V7_PAGE_SIZE = 4096;\n\n        private readonly Stream _stream;\n        private readonly LiteDB.BsonDocument _header;\n\n        private byte[] _buffer = new byte[V7_PAGE_SIZE];\n\n        public FileReaderV7(Stream stream, string password)\n        {\n            _stream = stream;\n\n            // only userVersion was avaiable in old file format versions\n            _header = this.ReadPage(0);\n\n            if (password == null && _header[\"salt\"].AsBinary.IsFullZero() == false)\n            {\n                throw new LiteDB.LiteException(\"Current data file requires password\");\n            }\n        }\n\n        /// <summary>\n        /// Read all collection based on header page\n        /// </summary>\n        public IEnumerable<string> GetCollections()\n        {\n            return _header[\"collections\"].AsDocument.Keys;\n        }\n\n        /// <summary>\n        /// Read all indexes from all collection pages\n        /// </summary>\n        public IEnumerable<IndexInfo> GetIndexes(string collection)\n        {\n            var pageID = (uint)_header[\"collections\"].AsDocument[collection].AsInt32;\n            var page = this.ReadPage(pageID);","sourceCodeStart":594,"sourceCodeEnd":630,"githubUrl":"https://github.com/JosefNemec/Playnite/blob/5911f4e964e628aa7a69c2030ab35101afa63067/source/Playnite/Database/Collections/LiteDBFileReaderV7.cs#L594-L630","documentation":"Thrown as LiteDB.LiteException by FileReaderV7 constructor when opening an old (v7 page format / LiteDB v4) database file that has a non-zero encryption salt in its header but no password was supplied. The salt indicates the file was created with password encryption enabled. The reader requires the password to decrypt pages.","triggerScenarios":"Migrating an encrypted old-format Playnite database without providing the password. The FileReaderV7(stream, password) constructor checks if the header's salt field is non-zero (indicating encryption) and password is null. This fires before any page decryption is attempted.","commonSituations":"The user had password protection enabled in an old Playnite version and is now migrating. The password was lost or forgotten. The migration code path does not prompt for or pass the database password. A portable/roaming database was moved to a new Playnite install without the password.","solutions":["Provide the database password to the migration/open API: ensure the password collection or prompt is wired into the FileReaderV7 constructor call.","If the password is known, enter it in Playnite's database settings before attempting migration.","If the password is lost, the database cannot be decrypted; restore from an unencrypted backup if available.","Disable encryption on the old Playnite install (if still accessible) before migrating: export data, create a new unencrypted DB, re-import."],"exampleFix":"// before — opening encrypted DB without password\nvar reader = new FileReaderV7(stream, password: null); // throws\n\n// after — prompt for or retrieve password before opening\nstring password = await PromptUserForDbPassword();\nvar reader = new FileReaderV7(stream, password);","handlingStrategy":"validation","validationCode":"// FileReaderV7 checks salt internally; pre-validate at the caller:\n// Read the salt bytes from the header page before constructing FileReaderV7\nbyte[] headerPage = new byte[4096];\nstream.Position = 0;\nstream.Read(headerPage, 0, 4096);\n// If salt (at its known offset) is non-zero, prompt for password before constructing the reader.","typeGuard":null,"tryCatchPattern":"try\n{\n    var reader = new FileReaderV7(stream, password);\n}\ncatch (LiteDB.LiteException ex) when (ex.Message.Contains(\"requires password\"))\n{\n    password = Dialogs.ShowInput(\"Database Password\", \"Enter the database password:\");\n    var reader = new FileReaderV7(stream, password);\n}","preventionTips":["Before migration, check if the database was encrypted (non-zero salt in header).","Prompt for password interactively when the salt indicates encryption.","Store the database password in the OS credential store for automatic migration."],"tags":["litedb","encryption","database-migration","password","v7-format"],"backgroundTag":null,"analyzedSha":"5911f4e964e628aa7a69c2030ab35101afa63067","analyzedAt":"2026-08-13T17:38:25.713Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}