microsoft/aspire · error · InvalidOperationException

Downloaded Aspire skills package contains multiple…

Error message

Downloaded Aspire skills package contains multiple skill-manifest.json files.

What it means

FindBundleRoot scans an extracted skills package for top-level directories containing skill-manifest.json. Exactly one bundle root is expected; discovering two or more means the archive packs multiple bundles ambiguously, so Aspire throws this InvalidOperationException rather than guessing which to install.

Solutions

  1. Repackage so only one top-level directory contains skill-manifest.json (nested skills belong under that single bundle root)
  2. Remove the extra skill-manifest.json files or split the package into separate bundles
  3. Re-download the official package instead of a hand-merged copy

Example fix

// before (archive layout)
bundleA/skill-manifest.json
bundleB/skill-manifest.json
// after
bundle/skill-manifest.json
bundle/skills/bundleA/...
bundle/skills/bundleB/...
Defensive patterns

Strategy: validation

Validate before calling

var manifests = Directory.EnumerateDirectories(extractDir, "skill-manifest.json", SearchOption.AllDirectories).ToList();
if (manifests.Count != 1) throw new Exception($"Expected exactly one skill-manifest.json, found {manifests.Count}.");

Try / catch

try { await provider.CreateAsync(...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("multiple skill-manifest.json")) { /* repackage with a single bundle root */ }

Prevention

When it happens

Trigger: AspireSkillsBundleProvider.CreateAsync extracts a downloaded package, and FindBundleRoot finds more than one top-level directory each containing a skill-manifest.json.

Common situations: Manually merging several bundles into one archive; a packaging script zipping multiple skill folders that each have their own manifest; accidental duplicate manifest placement during repackaging.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/d1f4a00c45ec3de9. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Cli/Agents/AspireSkills/AspireSkillsBundleProvider.cs:602

        var packageManifestPath = Path.Combine(packageDirectory, ManifestFileName);
        if (File.Exists(packageManifestPath))
        {
            return new DirectoryInfo(packageDirectory);
        }

        var topLevelBundleDirectories = Directory
            .EnumerateDirectories(extractionDirectory)
            .Where(directory => File.Exists(Path.Combine(directory, ManifestFileName)))
            .ToArray();

        if (topLevelBundleDirectories.Length == 1)
        {
            return new DirectoryInfo(topLevelBundleDirectories[0]);
        }

        if (topLevelBundleDirectories.Length > 1)
        {
            throw new InvalidOperationException("Downloaded Aspire skills package contains multiple skill-manifest.json files.");
        }

        throw new InvalidOperationException("Downloaded Aspire skills package does not contain skill-manifest.json.");
    }

    private static void CopyDirectory(string sourceDirectory, string targetDirectory)
    {
        Directory.CreateDirectory(targetDirectory);

        foreach (var sourceFile in Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories))
        {
            var relativePath = Path.GetRelativePath(sourceDirectory, sourceFile);
            var targetFile = Path.Combine(targetDirectory, relativePath);
            var targetFileDirectory = Path.GetDirectoryName(targetFile);
            if (!string.IsNullOrEmpty(targetFileDirectory))
            {
                Directory.CreateDirectory(targetFileDirectory);
            }

View on GitHub (pinned to 25830f84bd)