{"record":{"id":"28b74ecb5afc8187","repo":"microsoft/aspire","slug":"downloaded-aspire-skills-package-does-not-contain-skill","errorCode":null,"errorMessage":"Downloaded Aspire skills package does not contain skill-manifest.json.","messagePattern":"Downloaded Aspire skills package does not contain skill-manifest\\.json\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Cli/Agents/AspireSkills/AspireSkillsBundleProvider.cs","lineNumber":605,"sourceCode":"            return new DirectoryInfo(packageDirectory);\n        }\n\n        var topLevelBundleDirectories = Directory\n            .EnumerateDirectories(extractionDirectory)\n            .Where(directory => File.Exists(Path.Combine(directory, ManifestFileName)))\n            .ToArray();\n\n        if (topLevelBundleDirectories.Length == 1)\n        {\n            return new DirectoryInfo(topLevelBundleDirectories[0]);\n        }\n\n        if (topLevelBundleDirectories.Length > 1)\n        {\n            throw new InvalidOperationException(\"Downloaded Aspire skills package contains multiple skill-manifest.json files.\");\n        }\n\n        throw new InvalidOperationException(\"Downloaded Aspire skills package does not contain skill-manifest.json.\");\n    }\n\n    private static void CopyDirectory(string sourceDirectory, string targetDirectory)\n    {\n        Directory.CreateDirectory(targetDirectory);\n\n        foreach (var sourceFile in Directory.GetFiles(sourceDirectory, \"*\", SearchOption.AllDirectories))\n        {\n            var relativePath = Path.GetRelativePath(sourceDirectory, sourceFile);\n            var targetFile = Path.Combine(targetDirectory, relativePath);\n            var targetFileDirectory = Path.GetDirectoryName(targetFile);\n            if (!string.IsNullOrEmpty(targetFileDirectory))\n            {\n                Directory.CreateDirectory(targetFileDirectory);\n            }\n\n            File.Copy(sourceFile, targetFile, overwrite: true);\n        }","sourceCodeStart":587,"sourceCodeEnd":623,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Cli/Agents/AspireSkills/AspireSkillsBundleProvider.cs#L587-L623","documentation":"AspireSkillsBundleProvider locates the root directory of a downloaded skills bundle by searching for skill-manifest.json. When no directory in the extracted archive contains that manifest, FindBundleRoot throws this InvalidOperationException, meaning the archive is not a valid Aspire skills bundle layout.","triggerScenarios":"Downloaded/extracted GitHub release asset whose top-level directories (or the archive root) contain no skill-manifest.json; FindBundleRoot is called from bundleRoot during bundle creation.","commonSituations":"Publishing a release with the wrong artifact (zip without the manifest), mis-zipped archive that nests the manifest one level deeper than expected, corrupted or partially extracted download, or someone packaging skills manually and forgetting skill-manifest.json.","solutions":["Verify the release asset zip actually contains skill-manifest.json at its root or directly inside a single top-level directory","Re-download the bundle; a truncated download may have failed to extract the manifest","Regenerate and publish the skills bundle with the manifest included"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before installing, inspect the extracted bundle\nvar manifests = Directory.EnumerateFiles(extractDir, \"skill-manifest.json\", SearchOption.AllDirectories).ToList();\nif (manifests.Count == 0)\n    throw new InvalidOperationException($\"Bundle at {extractDir} has no skill-manifest.json — not a valid skills bundle.\");","typeGuard":null,"tryCatchPattern":"try\n{\n    await provider.CreateBundleAsync(archivePath);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"does not contain skill-manifest.json\"))\n{\n    logger.LogError(ex, \"Downloaded skills bundle is missing skill-manifest.json; re-download or use a different release.\");\n}","preventionTips":["Always publish release archives that contain skill-manifest.json at the root or one directory deep","Verify archive layout with CI checks before publishing a skills release","Use the official bundle tooling rather than hand-zipping directories"],"tags":["cli","skills-bundle","package-layout","manifest"],"backgroundTag":"file-not-found","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}