{"record":{"id":"c36d38ea07df051e","repo":"JosefNemec/Playnite","slug":"manifest-file-playnitepaths-extensionmanifestfil","errorCode":null,"errorMessage":"Manifest file ({PlaynitePaths.ExtensionManifestFileName}) not found!","messagePattern":"Manifest file \\((.+?)\\) not found!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"source/Tools/Playnite.Toolbox/Extensions.cs","lineNumber":189,"sourceCode":"                case ExtensionType.MetadataProvider:\r\n                    baseProjectName = metadataPluginProjectName;\r\n                    break;\r\n            }\r\n\r\n            File.Move(Path.Combine(outDir, baseProjectName + \".csproj\"), outProjectFile);\r\n            File.Move(Path.Combine(outDir, baseProjectName + \".sln\"), outSolutionFile);\r\n            FileSystem.ReplaceStringInFile(outProjectFile, baseProjectName, normalizedName);\r\n            FileSystem.ReplaceStringInFile(outSolutionFile, baseProjectName, normalizedName);\r\n            return outDir;\r\n        }\r\n\r\n        public static string PackageExtension(string extDirectory, string targetPath)\r\n        {\r\n            var dirInfo = new DirectoryInfo(extDirectory);\r\n            var manifestPath = Path.Combine(extDirectory, PlaynitePaths.ExtensionManifestFileName);\r\n            if (!File.Exists(manifestPath))\r\n            {\r\n                throw new Exception($\"Manifest file ({PlaynitePaths.ExtensionManifestFileName}) not found!\");\r\n            }\r\n\r\n            var extInfo = ExtensionInstaller.GetExtensionManifest(manifestPath);\r\n            if (extInfo.Id.IsNullOrEmpty())\r\n            {\r\n                throw new Exception(\"Cannot package extension, ID is missing!\");\r\n            }\r\n\r\n            extInfo.VerifyManifest();\r\n\r\n            var packedPath = Path.Combine(targetPath, $\"{Common.Paths.GetSafePathName(extInfo.Id).Replace(' ', '_')}_{extInfo.Version.ToString().Replace(\".\", \"_\")}{PlaynitePaths.PackedExtensionFileExtention}\");\r\n            FileSystem.PrepareSaveFile(packedPath);\r\n            var ignoreFiles = File.ReadAllLines(Paths.ExtFileIgnoreListPath);\r\n\r\n            using (var zipStream = new FileStream(packedPath, FileMode.Create))\r\n            {\r\n                using (var zipFile = new ZipArchive(zipStream, ZipArchiveMode.Create))\r\n                {\r","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/JosefNemec/Playnite/blob/5911f4e964e628aa7a69c2030ab35101afa63067/source/Tools/Playnite.Toolbox/Extensions.cs#L171-L207","documentation":"Thrown by Extensions.PackageExtension when the supplied extension directory does not contain extension.yaml (PlaynitePaths.ExtensionManifestFileName). The method resolves manifestPath = Path.Combine(extDirectory, \"extension.yaml\") and aborts before reading, zipping, or version-checking anything. It is a precondition check: the packer cannot proceed without the manifest that declares the extension's Id and Version.","triggerScenarios":"Calling PackageExtension(extDirectory, targetPath) where extDirectory points at a folder with no extension.yaml. Common triggers: passing the repository root instead of the built output folder, pointing at the parent of the extension folder, or running `pack` before the manifest file was written by `new`.","commonSituations":"Switching between an extension's source layout and its deployable layout; building a plugin and pointing Toolbox at /bin output that only has the DLL; cloning a template and renaming/moving extension.yaml; CWD-relative paths that resolve to the wrong directory.","solutions":["Verify extension.yaml actually exists under extDirectory: `ls extDirectory/extension.yaml` (the filename is exactly extension.yaml, not extension.yaml.txt).","Re-run `Toolbox new <type> <name>` to regenerate a valid extension scaffold that includes extension.yaml, then point PackageExtension at that output directory.","Pass the directory that directly contains the manifest, not a parent or sibling directory (PackageExtension does not recurse).","Confirm extDirectory is absolute or resolved against the intended base; relative paths are resolved against the process CWD, which for Toolbox is often unexpected."],"exampleFix":"// before\nExtensions.PackageExtension(@\".\\MyPlugin\", outDir); // no extension.yaml here\n\n// after\nvar extDir = Path.GetFullPath(@\".\\MyPlugin\\source\"); // folder containing extension.yaml\nif (!File.Exists(Path.Combine(extDir, PlaynitePaths.ExtensionManifestFileName)))\n    throw new FileNotFoundException(\"extension.yaml missing\", extDir);\nExtensions.PackageExtension(extDir, outDir);","handlingStrategy":"validation","validationCode":"var manifestPath = Path.Combine(extDirectory, PlaynitePaths.ExtensionManifestFileName);\nif (!File.Exists(manifestPath))\n    throw new FileNotFoundException($\"extension.yaml not found at {manifestPath}\", manifestPath);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass the directory that directly contains extension.yaml, resolved to an absolute path.","Assert File.Exists(manifestPath) immediately before calling PackageExtension.","Treat a missing extension.yaml as a build/scaffold bug, not a runtime condition — fix the source layout."],"tags":["extensions","packaging","manifest","toolbox","filesystem","precondition"],"backgroundTag":null,"analyzedSha":"5911f4e964e628aa7a69c2030ab35101afa63067","analyzedAt":"2026-08-13T17:38:25.713Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}