microsoft/aspire · error · InvalidOperationException
Aspire skills bundle path
Error message
Aspire skills bundle path '{0}' must be relative. What it means
NormalizeRelativePath rejects bundle paths that are rooted (absolute), such as '/etc/passwd' or 'C:\Windows\...'. Bundle contents must be addressed relative to the bundle root so extraction/copying can never target arbitrary filesystem locations. Aspire throws this InvalidOperationException when a rooted path is encountered.
Solutions
- Change the path to be relative to the bundle root, e.g. "skills/my-skill/SKILL.md"
- Strip any leading slash, drive letter, or UNC prefix from manifest entries
- Repackage the bundle with a tool that emits relative paths
Example fix
// before (skill-manifest.json)
{ "path": "/home/user/app/skills/my-skill/SKILL.md" }
// after
{ "path": "skills/my-skill/SKILL.md" } Defensive patterns
Strategy: validation
Validate before calling
if (Path.IsPathRooted(entry.Path) || Path.IsPathFullyQualified(entry.Path))
throw new Exception($"Path '{entry.Path}' must be relative to the bundle root."); Try / catch
try { await provider.CreateAsync(...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("must be relative")) { /* rewrite manifest paths as relative */ } Prevention
- Always author manifest paths relative to the bundle root
- Never paste absolute filesystem paths into skill manifests
- Test bundles on both Windows and Linux to catch rooted-path mistakes
When it happens
Trigger: A manifest entry or bundle path in skill-manifest.json is an absolute path (leading '/', drive letter, or UNC path) and is passed through AspireSkillsBundleProvider.CreateAsync.
Common situations: Authoring a manifest on Windows with 'C:\...' paths; copy-pasting absolute file paths from an editor; a packaging tool emitting absolute paths.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Aspire skills bundle contains an empty relative path.
- Aspire skills bundle path
- Aspire skills archive entry
- Aspire skills bundle skill
- Downloaded Aspire skills package contains multiple…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/495255ce509931de.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Cli/Agents/AspireSkills/AspireSkillsBundleProvider.cs:414
}
return null;
}
internal static string NormalizeRelativePath(string? relativePath)
{
if (string.IsNullOrWhiteSpace(relativePath))
{
throw new InvalidOperationException("Aspire skills bundle contains an empty relative path.");
}
var normalizedPath = relativePath
.Replace('/', Path.DirectorySeparatorChar)
.Replace('\\', Path.DirectorySeparatorChar);
if (Path.IsPathRooted(normalizedPath))
{
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Aspire skills bundle path '{0}' must be relative.", relativePath));
}
var segments = normalizedPath.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries);
if (segments.Length == 0 || segments.Any(static segment => !IsPortablePathSegment(segment)))
{
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Aspire skills bundle path '{0}' is not safe.", relativePath));
}
return Path.Combine(segments);
}
private static bool IsPortablePathSegment(string segment)
{
// Bundle paths can be validated on one platform and installed on another. Reject the
// Windows-invalid character set everywhere so ':' cannot create an NTFS alternate data
// stream and other invalid filenames cannot enter a cached bundle.
// See https://learn.microsoft.com/windows/win32/fileio/naming-a-file.
return segment is not "." and not ".." &&View on GitHub (pinned to 25830f84bd)