{"record":{"id":"332b2b45cdae3836","repo":"JosefNemec/Playnite","slug":"package-content-invalid","errorCode":null,"errorMessage":"Package content invalid.","messagePattern":"Package content invalid\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"source/Playnite/Plugins/ExtensionInstaller.cs","lineNumber":196,"sourceCode":"            File.Delete(PlaynitePaths.ExtensionQueueFilePath);\r\n            currentQueue = new List<ExtensionInstallQueueItem>();\r\n            return installedExts;\r\n        }\r\n\r\n        public static ExtensionInstallResult InstallPackedFile<T>(string packagePath, string nanifestFileName, string rootDir, Func<string, T> newMan) where T : BaseExtensionManifest\r\n        {\r\n            logger.Info($\"Installing extenstion/theme {packagePath}\");\r\n            var manifest = GetPackedManifest<T>(packagePath, nanifestFileName);\r\n            if (manifest == null)\r\n            {\r\n                throw new FileNotFoundException(\"Extenstion/theme manifest not found.\");\r\n            }\r\n\r\n            var entries = Archive.GetArchiveFiles(packagePath);\r\n            if (entries.Any(a => a.EndsWith(\".sln\", StringComparison.OrdinalIgnoreCase)))\r\n            {\r\n                // Check for themes that are not packaged via Toolbox.\r\n                throw new Exception(\"Package content invalid.\");\r\n            }\r\n\r\n            if (manifest is ThemeManifest themeMan)\r\n            {\r\n                rootDir = Path.Combine(rootDir, themeMan.Mode.ToString());\r\n            }\r\n\r\n            var wasUpdated = false;\r\n            var installDir = Path.Combine(rootDir, Paths.GetSafePathName(manifest.Id));\r\n            if (Directory.Exists(installDir))\r\n            {\r\n                wasUpdated = true;\r\n                logger.Debug($\"Replacing existing extenstion/theme installation: {installDir}.\");\r\n            }\r\n\r\n            FileSystem.CreateDirectory(installDir, true);\r\n            ZipFile.ExtractToDirectory(packagePath, installDir);\r\n            if (Paths.AreEqual(PlaynitePaths.TempPath, Path.GetDirectoryName(packagePath)))\r","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/JosefNemec/Playnite/blob/5911f4e964e628aa7a69c2030ab35101afa63067/source/Playnite/Plugins/ExtensionInstaller.cs#L178-L214","documentation":"Thrown by InstallPackedFile when the package archive contains a .sln file, which indicates the package is unpackaged source rather than a Toolbox-built extension/theme pack. Playnite refuses to install raw source solutions because they are not deployable add-ons.","triggerScenarios":"InstallPackedFile is given an archive whose entries include any file ending in .sln. Detected via Archive.GetArchiveFiles(packagePath).Any(... \".sln\").","commonSituations":"Developer or user zipped the source folder (including the .sln) instead of running Toolbox packaging; a git repo export was packaged rather than a build artifact.","solutions":["Build the package with Playnite Toolbox (pack command) to produce a proper installable archive without the .sln.","Exclude .sln and source files when zipping; ensure the archive contains only the built output and manifest.","Verify package contents with Archive.GetArchiveFiles before attempting install."],"exampleFix":"// before\nif (entries.Any(a => a.EndsWith(\".sln\", StringComparison.OrdinalIgnoreCase))) { throw new Exception(\"Package content invalid.\"); }\n\n// after — clearer guidance\nif (entries.Any(a => a.EndsWith(\".sln\", StringComparison.OrdinalIgnoreCase))) {\n    throw new Exception(\"Package contains a .sln file; it appears to be source, not a Toolbox-built pack. Build it with Toolbox first.\");\n}","handlingStrategy":"validation","validationCode":"// Reject source bundles before install.\nif (Archive.GetArchiveFiles(packagePath).Any(a => a.EndsWith(\".sln\", StringComparison.OrdinalIgnoreCase))) {\n    logger.Error($\"{packagePath} is a source bundle, not an installable pack.\");\n    return;\n}","typeGuard":"static bool IsInstallablePackage(string packagePath) =>\n    !Archive.GetArchiveFiles(packagePath).Any(a => a.EndsWith(\".sln\", StringComparison.OrdinalIgnoreCase));","tryCatchPattern":null,"preventionTips":["Build with Toolbox rather than zipping source folders.","Exclude .sln and source files from release archives.","Educate users that source downloads are not installable."],"tags":["addon","installer","packaging","validation"],"backgroundTag":null,"analyzedSha":"5911f4e964e628aa7a69c2030ab35101afa63067","analyzedAt":"2026-08-13T17:38:25.713Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}