microsoft/aspire · error · InvalidOperationException

Failed to parse project.assets.json

Error message

Failed to parse project.assets.json

What it means

After confirming the assets file exists, Resolve parses it with NuGet's LockFileFormat. If parsing yields a null LockFile — meaning the file content is not a valid project.assets.json structure — an InvalidOperationException is thrown.

Solutions

  1. Delete the obj (and bin) directory and re-run `dotnet restore` to regenerate a valid assets file.
  2. Verify project.assets.json is valid JSON and was produced by `dotnet restore`, not hand-edited.
  3. Avoid concurrent restore/build operations on the same project directory.

Example fix

// before
resolver.Resolve("obj/project.assets.json", "net10.0", null); // corrupt file
// after
Directory.Delete("obj", recursive: true);
Process.Start("dotnet", "restore").WaitForExit();
resolver.Resolve("obj/project.assets.json", "net10.0", null);
Defensive patterns

Strategy: try-catch

Validate before calling

try { using var doc = JsonDocument.Parse(File.ReadAllText(assetsPath)); }
catch (JsonException) { Directory.Delete(Path.GetDirectoryName(assetsPath)!, recursive: true); /* re-restore */ }

Try / catch

try { resolver.Resolve(assetsPath, tfm, rid); }
catch (InvalidOperationException ex) when (ex.Message == "Failed to parse project.assets.json")
{ RestoreProject(projectDir); resolver.Resolve(assetsPath, tfm, rid); }

Prevention

When it happens

Trigger: Calling Resolve on a project.assets.json that exists but is corrupt, truncated, empty, or written by an incompatible tooling version so LockFileFormat.Read returns null.

Common situations: An interrupted restore leaving a partial assets file, manual edits to project.assets.json, or concurrent builds writing to the same obj directory.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Managed/NuGet/Commands/NuGetPackageAssetResolver.cs:61

internal static class NuGetPackageAssetResolver
{
    public static NuGetPackageAssetResolution Resolve(
        string assetsPath,
        string framework,
        string? runtimeIdentifier,
        Action<string>? verboseLog = null)
    {
        if (!File.Exists(assetsPath))
        {
            throw new FileNotFoundException($"Assets file not found: {assetsPath}", assetsPath);
        }

        var lockFileFormat = new LockFileFormat();
        var lockFile = lockFileFormat.Read(assetsPath);
        if (lockFile is null)
        {
            throw new InvalidOperationException("Failed to parse project.assets.json");
        }

        var effectiveRuntimeIdentifier = string.IsNullOrWhiteSpace(runtimeIdentifier)
            ? RuntimeInformation.RuntimeIdentifier
            : runtimeIdentifier;
        var target = ResolveTarget(lockFile, framework, effectiveRuntimeIdentifier);
        if (target is null)
        {
            throw new InvalidOperationException(
                $"Target framework '{framework}' not found in assets file. Available targets: {string.Join(", ", lockFile.Targets.Select(t => t.TargetFramework.GetShortFolderName()))}");
        }

        var packagesPath = GetPackagesPath(lockFile);
        var targetFramework = target.TargetFramework.GetShortFolderName();
        var assets = new List<NuGetPackageAsset>();
        var skippedCount = 0;
        var runtimeIdentifiers = GetRuntimeIdentifiers(assetsPath, framework, effectiveRuntimeIdentifier);
        var packageLibraries = lockFile.Libraries

View on GitHub (pinned to 25830f84bd)