{"record":{"id":"f5246d5e2a8df6fd","repo":"JosefNemec/Playnite","slug":"loc-generalextensionpackageerror","errorCode":null,"errorMessage":"LOC.GeneralExtensionPackageError","messagePattern":"LOC\\.GeneralExtensionPackageError","errorType":"exception","errorClass":"LocalizedException","httpStatus":null,"severity":"error","filePath":"source/Playnite/Plugins/ExtensionInstaller.cs","lineNumber":335,"sourceCode":"        private static void QueueExtensionOperation(string extensionPath, ExtInstallType installationType)\r\n        {\r\n            if (currentQueue.FirstOrDefault(a => a.Path == extensionPath) == null)\r\n            {\r\n                currentQueue.Add(new ExtensionInstallQueueItem(extensionPath, installationType));\r\n            }\r\n\r\n            FileSystem.WriteStringToFile(PlaynitePaths.ExtensionQueueFilePath, Serialization.ToJson(currentQueue));\r\n        }\r\n\r\n        public static void VerifyExtensionPackage(string packagePath)\r\n        {\r\n            using (var zip = ZipFile.OpenRead(packagePath))\r\n            {\r\n                var manifestEntry = zip.GetEntry(PlaynitePaths.ExtensionManifestFileName);\r\n                if (manifestEntry == null)\r\n                {\r\n                    logger.Error(\"Extension package is invalid, no manifest found.\");\r\n                    throw new LocalizedException(LOC.GeneralExtensionPackageError);\r\n                }\r\n\r\n                using (var logStream = manifestEntry.Open())\r\n                {\r\n                    using (TextReader tr = new StreamReader(logStream))\r\n                    {\r\n                        var manifest = Serialization.FromYaml<ExtensionManifest>(tr.ReadToEnd());\r\n                        if (manifest.Id.IsNullOrEmpty())\r\n                        {\r\n                            logger.Error(\"Extension package is invalid, no extension ID found.\");\r\n                            throw new LocalizedException(LOC.GeneralExtensionPackageError);\r\n                        }\r\n\r\n                        if (!Version.TryParse(manifest.Version, out var _))\r\n                        {\r\n                            logger.Error($\"Extension package is invalid, version is not in correct format {manifest.Version}.\");\r\n                            throw new LocalizedException(LOC.GeneralExtensionPackageError);\r\n                        }\r","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/JosefNemec/Playnite/blob/5911f4e964e628aa7a69c2030ab35101afa63067/source/Playnite/Plugins/ExtensionInstaller.cs#L317-L353","documentation":"Thrown as LocalizedException(LOC.GeneralExtensionPackageError) by VerifyExtensionPackage when the zip archive has no extension manifest entry (PlaynitePaths.ExtensionManifestFileName) or the parsed manifest has an empty Id. Both defects make the package unusable; the localized exception surfaces a user-facing message.","triggerScenarios":"VerifyExtensionPackage opens a zip that either lacks the manifest entry (zip.GetEntry returns null) or whose manifest YAML deserializes to an object with null/empty Id. Occurs during pre-install validation of an extension package.","commonSituations":"Corrupt or truncated download of an extension pack; package built without embedding the manifest; manifest present but Id field blank due to a packaging bug.","solutions":["Re-download the extension package in case of truncation/corruption.","Rebuild the package ensuring the manifest file is at the archive root with a non-empty Id.","Before installing, verify the zip contains the manifest entry and that its Id is populated."],"exampleFix":"// before\nvar manifestEntry = zip.GetEntry(PlaynitePaths.ExtensionManifestFileName);\nif (manifestEntry == null) { throw new LocalizedException(LOC.GeneralExtensionPackageError); }\n\n// after\nvar manifestEntry = zip.GetEntry(PlaynitePaths.ExtensionManifestFileName);\nif (manifestEntry == null) {\n    logger.Error($\"Package {packagePath} missing manifest entry '{PlaynitePaths.ExtensionManifestFileName}'.\");\n    throw new LocalizedException(LOC.GeneralExtensionPackageError);\n}","handlingStrategy":"validation","validationCode":"// Pre-verify the manifest entry and Id before installing.\nusing (var zip = ZipFile.OpenRead(packagePath)) {\n    var entry = zip.GetEntry(PlaynitePaths.ExtensionManifestFileName);\n    if (entry == null) { logger.Error(\"No manifest entry.\"); return; }\n    using var tr = new StreamReader(entry.Open());\n    var m = Serialization.FromYaml<ExtensionManifest>(tr.ReadToEnd());\n    if (m.Id.IsNullOrEmpty()) { logger.Error(\"Manifest Id empty.\"); return; }\n}","typeGuard":"static bool PackageManifestValid(string packagePath) {\n    using var zip = ZipFile.OpenRead(packagePath);\n    var entry = zip.GetEntry(PlaynitePaths.ExtensionManifestFileName);\n    if (entry == null) return false;\n    using var tr = new StreamReader(entry.Open());\n    var m = Serialization.FromYaml<ExtensionManifest>(tr.ReadToEnd());\n    return !m.Id.IsNullOrEmpty();\n}","tryCatchPattern":"try { ExtensionInstaller.VerifyExtensionPackage(packagePath); }\ncatch (LocalizedException) { Dialogs.ShowMessage(resources.GetString(LOC.GeneralExtensionPackageError), LOC.Error, MessageBoxButton.OK, MessageBoxImage.Error); }","preventionTips":["Re-download packages suspected of corruption.","Ensure packages are built with a non-empty manifest Id.","Run VerifyExtensionPackage before queueing an install."],"tags":["addon","installer","manifest","validation","packaging"],"backgroundTag":null,"analyzedSha":"5911f4e964e628aa7a69c2030ab35101afa63067","analyzedAt":"2026-08-13T17:38:25.713Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}