microsoft/aspire · error · InvalidDataException
Deployment state must contain a JSON object.
Error message
Deployment state must contain a JSON object.
What it means
ParseStateFile parses the deployment state file and throws InvalidDataException if JsonNode.Parse does not yield a JsonObject, i.e. the file contains a JSON array, string, number, or invalid/truncated JSON rather than the expected top-level object. Parsing tolerates comments and trailing commas but the root must be an object.
Solutions
- Open the state file and fix the root to be a JSON object ({...}); remove arrays or bare values at the top level.
- If the file is truncated or corrupt, delete it and re-run the deployment so state is regenerated.
- Restore the file from backup or source control if it was hand-edited.
Example fix
// before (state file)
[ { "a": 1 } ]
// after
{ "a": 1 } Defensive patterns
Strategy: validation
Validate before calling
// Validate the state file before use
using var doc = JsonNode.Parse(File.ReadAllText(statePath),
documentOptions: new JsonDocumentOptions { CommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
if (doc is not JsonObject)
{
throw new InvalidDataException($"{statePath} must contain a top-level JSON object.");
} Type guard
static bool IsValidStateFile(string content) =>
JsonNode.Parse(content) is JsonObject; Try / catch
try { var state = await manager.LoadStateFileAsync(path, ct); }
catch (InvalidDataException ex) when (ex.Message.Contains("must contain a JSON object"))
{
// quarantine the corrupt file and start fresh
File.Move(path, path + ".corrupt", overwrite: true);
} Prevention
- Don't hand-edit deployment state files; if you must, keep the root as a JSON object.
- Keep backups of the state file before manual changes.
- Avoid killing processes mid-write; check for truncated files after crashes.
When it happens
Trigger: Calling LoadStateFileAsync/LoadStateFile when the deployment state file was hand-edited to an array or scalar, truncated by a crashed writer, or is empty/corrupt on disk.
Common situations: Manual edits of ~/.aspire/deployment state files; a previous run was killed mid-write; file synced/truncated by tooling; user pasted a JSON array of key/value pairs instead of an object.
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
- ' ' must be a JSON string.
- ' ' must be a JSON string.
- ' ' must contain a JSON object.
- ' ' must be a JSON object.
- Resource command argument
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/4b4ca6b4a8db0fa6.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting/Pipelines/Internal/DeploymentStateManagerBase.cs:138
return ParseStateFile(fileContent);
}
private static JsonObject ParseStateFile(string? fileContent)
{
if (fileContent is null)
{
return [];
}
var jsonDocumentOptions = new JsonDocumentOptions
{
CommentHandling = JsonCommentHandling.Skip,
AllowTrailingCommas = true,
};
if (JsonNode.Parse(fileContent, documentOptions: jsonDocumentOptions) is not JsonObject flattenedState)
{
throw new InvalidDataException("Deployment state must contain a JSON object.");
}
return JsonFlattener.UnflattenJsonObject(flattenedState);
}
/// <inheritdoc/>
public async Task SaveStateAsync(JsonObject state, CancellationToken cancellationToken = default)
{
await _stateLock.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
await SaveStateToStorageAsync(state, sectionName: null, originalSectionData: null, cancellationToken).ConfigureAwait(false);
}
finally
{
_stateLock.Release();
}
}View on GitHub (pinned to 25830f84bd)