microsoft/aspire · error · InvalidOperationException

Integration closure manifest is inconsistent. Sources

Error message

Integration closure manifest is inconsistent. Sources: {sourcePaths.Count}, metadata: {metadataLines.Count}, targets: {targetPaths.Count}.

What it means

PrebuiltAppHostServer reads three parallel manifest files (sources, metadata lines, targets) describing the integration closure after a bundled restore/build. All three must have the same line count because line N of each file describes the same artifact. If the counts differ, the manifest was written inconsistently and the closure cannot be reconstructed safely, so the CLI throws InvalidOperationException.

Solutions

  1. Delete the bundle/restore output directory and rebuild the prebuilt AppHost so all three manifests are regenerated together.
  2. Regenerate the manifest with the same Aspire CLI version that consumes it; do not mix versions.
  3. If hand-maintained, verify each file has one entry per artifact in identical order (sources[i], metadata[i], targets[i] describe the same artifact).

Example fix

// before: manifest edited, sources has 5 lines but targets has 4
// after:
aspire publish / dotnet build # regenerate the closure so Sources: 5, metadata: 5, targets: 5
Defensive patterns

Strategy: validation

Validate before calling

var src = File.ReadAllLines(closureSourcesPath).Where(l => !string.IsNullOrWhiteSpace(l)).Count();
var meta = File.ReadAllLines(closureMetadataPath).Where(l => !string.IsNullOrWhiteSpace(l)).Count();
var tgt = File.ReadAllLines(closureTargetsPath).Where(l => !string.IsNullOrWhiteSpace(l)).Count();
if (src != meta || src != tgt) throw new InvalidOperationException($"Closure manifests out of sync: sources={src}, metadata={meta}, targets={tgt}; rebuild the bundle.");

Type guard

static bool ClosureManifestsConsistent(int sources, int metadata, int targets) => sources == metadata && sources == targets;

Try / catch

try { await server.LoadClosureAsync(ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("closure manifest is inconsistent"))
{ logger.LogWarning(ex, "Corrupt closure manifest; regenerating bundle"); await RegenerateBundleAsync(ct); }

Prevention

When it happens

Trigger: Loading a prebuilt AppHost bundle whose closure manifest files (sources, metadata, targets) were produced with mismatched line counts — e.g. a partially written, hand-edited, or stale manifest from a different build, or a manifest where blank lines were filtered differently at write time.

Common situations: Copying only some manifest files from another build output; an interrupted build that wrote one manifest completely but not others; manually editing one manifest (adding/removing a path) without updating the other two; using a bundle generated by an older CLI version with a different manifest format.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Cli/Projects/PrebuiltAppHostServer.cs:827

            _logger.LogError("Integration project build failed. Output:\n{BuildOutput}", outputLines);
            throw new AppHostServerPrepareFailedException(GetIntegrationBuildFailureMessage(buildOutput), buildOutput);
        }

        if (restoreFingerprint is not null && !skipRestore)
        {
            await WriteRestoreStampAsync(restoreDir, restoreFingerprint, _logger, cancellationToken).ConfigureAwait(false);
        }

        var closureSourcesPath = Path.Combine(restoreDir, ClosureSourcesFileName);
        var closureMetadataPath = Path.Combine(restoreDir, ClosureMetadataFileName);
        var closureTargetsPath = Path.Combine(restoreDir, ClosureTargetsFileName);

        var sourcePaths = await ReadManifestFileAsync(closureSourcesPath, cancellationToken).ConfigureAwait(false);
        var metadataLines = await ReadManifestFileAsync(closureMetadataPath, cancellationToken).ConfigureAwait(false);
        var targetPaths = await ReadManifestFileAsync(closureTargetsPath, cancellationToken).ConfigureAwait(false);
        if (sourcePaths.Count != metadataLines.Count || sourcePaths.Count != targetPaths.Count)
        {
            throw new InvalidOperationException(
                $"Integration closure manifest is inconsistent. Sources: {sourcePaths.Count}, metadata: {metadataLines.Count}, targets: {targetPaths.Count}.");
        }

        var projectRefAssemblyNames = await ReadProjectRefAssemblyNamesAsync(
            Path.Combine(restoreDir, ProjectRefAssemblyNamesFileName),
            cancellationToken).ConfigureAwait(false);
        var appSettingsContent = CreateAppSettingsContent(packageRefs, projectRefAssemblyNames);
        var packageFingerprints = await ReadPackageFingerprintsAsync(
            Path.Combine(restoreDir, "obj", ProjectAssetsFileName),
            cancellationToken).ConfigureAwait(false);

        var closureEntries = new List<AppHostServerClosureSource>(sourcePaths.Count);
        for (var i = 0; i < sourcePaths.Count; i++)
        {
            var metadata = ParseClosureMetadata(metadataLines[i]);
            var packageSha512 = TryGetPackageFingerprint(packageFingerprints, metadata);

            closureEntries.Add(new AppHostServerClosureSource(

View on GitHub (pinned to 25830f84bd)