microsoft/aspire · error · JsonException
Expected a JSON array.
Error message
Expected a JSON array.
What it means
DeserializeArrayIncrementally parses a JSON string as an array of T using Utf8JsonReader. If the first token is not the start of an array, a JsonException with this message is thrown; truly malformed JSON exceptions are intentionally allowed to propagate. This guards the incremental reader so it never loops over a non-array document.
Solutions
- Wrap the payload in an array before parsing: if the first non-whitespace char is '{', serialize as [payload].
- For backwards compatibility, detect a leading '{' and fall back to parsing a single object then treat it as a one-element list.
- Validate the stored JSON shape where it is written to prevent bad payloads from being persisted.
Example fix
// before
var messages = GenAIMessageParsingHelper.DeserializeArrayIncrementally<ChatMessage>(json);
// after
var trimmed = json.TrimStart();
if (trimmed.StartsWith('{'))
{
json = "[" + json + "]"; // older payloads stored a single message object
}
var messages = GenAIMessageParsingHelper.DeserializeArrayIncrementally<ChatMessage>(json); Defensive patterns
Strategy: try-catch
Validate before calling
var trimmed = json.TrimStart();
if (trimmed.Length == 0 || (trimmed[0] != '['))
{
// normalize single-object payloads to arrays before parsing
if (trimmed.StartsWith('{')) json = "[" + json + "]";
} Try / catch
try
{
items = GenAIMessageParsingHelper.DeserializeArrayIncrementally<T>(json);
}
catch (JsonException ex)
{
logger.LogWarning(ex, "Payload is not a JSON array; skipping malformed telemetry entry");
} Prevention
- Always persist GenAI chat messages as a JSON array, even for a single message.
- Validate payload shape at write time in the telemetry store.
- Handle legacy single-object payloads with a normalization step.
When it happens
Trigger: Calling DeserializeArrayIncrementally with input whose first JSON token is an object, string, number, or null instead of '[' — e.g. telemetry/store payloads where a single GenAI message object was saved without wrapping it in an array.
Common situations: Older OpenTelemetry GenAI telemetry stored a single chat message object rather than an array of messages; hand-edited or truncated JSON files in the telemetry store; producers changed shape between versions.
Related errors
- Expected property name.
- Expected start of chat message object.
- Error deserializing GenAI message content. Error description
- Unexpected end of JSON while reading property value.
- Unexpected end of JSON while reading role value.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/490d33e3cfad2543.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Dashboard/Model/GenAI/GenAIMessageParsingHelper.cs:36
{
var bytes = Encoding.UTF8.GetBytes(json);
var readerOptions = new JsonReaderOptions
{
CommentHandling = JsonCommentHandling.Skip,
AllowTrailingCommas = true,
};
var reader = new Utf8JsonReader(bytes, readerOptions);
return DeserializeArrayIncrementally(ref reader, readElement);
}
internal static (List<T> items, bool truncated) DeserializeArrayIncrementally<T>(ref Utf8JsonReader reader, ReadElement<T> readElement)
{
var items = new List<T>();
// Read start of array. Let exceptions propagate for truly invalid JSON.
if (!reader.Read() || reader.TokenType != JsonTokenType.StartArray)
{
throw new JsonException("Expected a JSON array.");
}
while (true)
{
bool readSuccess;
try
{
readSuccess = reader.Read();
}
catch (JsonException)
{
return (items, true);
}
if (!readSuccess)
{
return (items, true);
}View on GitHub (pinned to 25830f84bd)