JosefNemec/Playnite · error · Exception
Package content invalid.
Error message
Package content invalid.
What it means
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.
Source
Thrown at source/Playnite/Plugins/ExtensionInstaller.cs:196
File.Delete(PlaynitePaths.ExtensionQueueFilePath);
currentQueue = new List<ExtensionInstallQueueItem>();
return installedExts;
}
public static ExtensionInstallResult InstallPackedFile<T>(string packagePath, string nanifestFileName, string rootDir, Func<string, T> newMan) where T : BaseExtensionManifest
{
logger.Info($"Installing extenstion/theme {packagePath}");
var manifest = GetPackedManifest<T>(packagePath, nanifestFileName);
if (manifest == null)
{
throw new FileNotFoundException("Extenstion/theme manifest not found.");
}
var entries = Archive.GetArchiveFiles(packagePath);
if (entries.Any(a => a.EndsWith(".sln", StringComparison.OrdinalIgnoreCase)))
{
// Check for themes that are not packaged via Toolbox.
throw new Exception("Package content invalid.");
}
if (manifest is ThemeManifest themeMan)
{
rootDir = Path.Combine(rootDir, themeMan.Mode.ToString());
}
var wasUpdated = false;
var installDir = Path.Combine(rootDir, Paths.GetSafePathName(manifest.Id));
if (Directory.Exists(installDir))
{
wasUpdated = true;
logger.Debug($"Replacing existing extenstion/theme installation: {installDir}.");
}
FileSystem.CreateDirectory(installDir, true);
ZipFile.ExtractToDirectory(packagePath, installDir);
if (Paths.AreEqual(PlaynitePaths.TempPath, Path.GetDirectoryName(packagePath)))
View on GitHub (pinned to 5911f4e964)
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.
Example fix
// before
if (entries.Any(a => a.EndsWith(".sln", StringComparison.OrdinalIgnoreCase))) { throw new Exception("Package content invalid."); }
// after — clearer guidance
if (entries.Any(a => a.EndsWith(".sln", StringComparison.OrdinalIgnoreCase))) {
throw new Exception("Package contains a .sln file; it appears to be source, not a Toolbox-built pack. Build it with Toolbox first.");
} Defensive patterns
Strategy: validation
Validate before calling
// Reject source bundles before install.
if (Archive.GetArchiveFiles(packagePath).Any(a => a.EndsWith(".sln", StringComparison.OrdinalIgnoreCase))) {
logger.Error($"{packagePath} is a source bundle, not an installable pack.");
return;
} Type guard
static bool IsInstallablePackage(string packagePath) =>
!Archive.GetArchiveFiles(packagePath).Any(a => a.EndsWith(".sln", StringComparison.OrdinalIgnoreCase)); Prevention
- Build with Toolbox rather than zipping source folders.
- Exclude .sln and source files from release archives.
- Educate users that source downloads are not installable.
When it happens
Trigger: InstallPackedFile is given an archive whose entries include any file ending in .sln. Detected via Archive.GetArchiveFiles(packagePath).Any(... ".sln").
Common situations: 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.
Related errors
- LOC.GeneralExtensionPackageError
- Extenstion/theme manifest not found.
- No addon manifest installer url.
- Extension version string must be a real version!
- LOC.GeneralThemePackageError
AI-assisted analysis of JosefNemec/Playnite@5911f4e964 (2026-08-13).
Data as JSON: /api/errors/332b2b45cdae3836.
Report an issue: GitHub.