microsoft/aspire · error · JsonException
Expected StartObject, got
Error message
Expected StartObject, got {reader.TokenType} What it means
FlexibleBooleanDictionaryConverter.Read expects the value of a dictionary-shaped config property to be a JSON object; when the token is anything else it throws JsonException naming the actual token type. This guards the Dictionary<string,bool> deserialization path.
Solutions
- Fix the JSON so the property is an object with boolean (or 'true'/'false' string) values.
- Check the schema the CLI expects for this configuration section and restructure the value accordingly.
- If null should be tolerated, note the converter already returns null for Null token; only other non-object tokens throw.
Example fix
// before
"featureFlags": "enabled"
// after
"featureFlags": { "MyFeature": "true" } Defensive patterns
Strategy: validation
Validate before calling
using var doc = JsonDocument.Parse(json);
if (doc.RootElement.TryGetProperty("featureFlags", out var flags) && flags.ValueKind != JsonValueKind.Object && flags.ValueKind != JsonValueKind.Null)
throw new FormatException("featureFlags must be a JSON object."); Try / catch
try
{
var config = JsonSerializer.Deserialize<MyConfig>(json, options);
}
catch (JsonException ex) when (ex.Message.StartsWith("Expected StartObject"))
{
logger.LogError(ex, "Config section expected to be an object but was another JSON kind.");
} Prevention
- Keep dictionary-shaped config values as JSON objects, never scalars or arrays.
- Validate config JSON structure before deserialization.
- Update config files when migrating between schema versions.
When it happens
Trigger: Feeding System.Text.Json a JSON document where a property mapped to Dictionary<string,bool> is a string, array, number, or null token instead of an object, e.g. "featureFlags": "enabled".
Common situations: Config schema drift — user writes a flat value where a nested map is required; migrating from a different config format; copy/paste errors in JSON.
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
- Cannot convert string
- Invalid boolean value
- Cannot convert to boolean for key
- Error deserializing GenAI message content. Error description
- Expected a non-empty Kubernetes MicroTime value.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/930069a9fe310805.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Cli/Configuration/FlexibleBooleanDictionaryConverter.cs:25
namespace Aspire.Cli.Configuration;
/// <summary>
/// A JSON converter that handles Dictionary<string, bool> with flexible boolean parsing.
/// Accepts both actual boolean values (true/false) and string representations ("true"/"false").
/// This provides backward compatibility for settings files that may have string values.
/// </summary>
internal sealed class FlexibleBooleanDictionaryConverter : JsonConverter<Dictionary<string, bool>>
{
public override Dictionary<string, bool>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
{
return null;
}
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException($"Expected StartObject, got {reader.TokenType}");
}
var dictionary = new Dictionary<string, bool>();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
return dictionary;
}
if (reader.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException($"Expected PropertyName, got {reader.TokenType}");
}
var key = reader.GetString() ?? throw new JsonException("Property name cannot be null");
View on GitHub (pinned to 25830f84bd)