{"record":{"id":"5818d6b5ad86fda6","repo":"microsoft/aspire","slug":"expected-property-name","errorCode":null,"errorMessage":"Expected property name.","messagePattern":"Expected property name\\.","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Dashboard/Model/GenAI/GenAIMessageParsingHelper.cs","lineNumber":107,"sourceCode":"        if (reader.TokenType != JsonTokenType.StartObject)\n        {\n            throw new JsonException(\"Expected start of chat message object.\");\n        }\n\n        string? role = null;\n        List<MessagePart>? parts = null;\n        var partsTruncated = false;\n\n        while (reader.Read())\n        {\n            if (reader.TokenType == JsonTokenType.EndObject)\n            {\n                break;\n            }\n\n            if (reader.TokenType != JsonTokenType.PropertyName)\n            {\n                throw new JsonException(\"Expected property name.\");\n            }\n\n            var propertyName = reader.GetString();\n\n            switch (propertyName)\n            {\n                case \"role\":\n                    if (!reader.Read())\n                    {\n                        throw new JsonException(\"Unexpected end of JSON while reading role value.\");\n                    }\n                    role = reader.GetString();\n                    break;\n                case \"parts\":\n                    // DeserializeArrayIncrementally reads the StartArray token itself.\n                    (parts, partsTruncated) = DeserializeArrayIncrementally<MessagePart>(ref reader, ReadMessagePart);\n                    break;\n                default:","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Dashboard/Model/GenAI/GenAIMessageParsingHelper.cs#L89-L125","documentation":"GenAIMessageParsingHelper.ReadChatMessage manually walks a GenAI message JSON object with Utf8JsonReader. After reading '{' or consuming a property value it expects the next token to be a property name; anything else means the JSON is not shaped like a chat message object, so it throws JsonException. It is a guard against malformed or non-object payloads being rendered in the GenAI visualizer.","triggerScenarios":"Reading a telemetry GenAI chat message whose JSON at the current position is not an object with property names — e.g. the value of a message field is an array, string, or number instead of an object, or the JSON is truncated mid-structure so a non-property token appears where a name is expected.","commonSituations":"OTLP logs/traces where the GenAI message body was serialized by a different schema version or custom instrumentation; a user pasting/importing hand-edited telemetry JSON; truncated payloads saved from an export.","solutions":["Inspect the raw JSON stored in the telemetry entry and confirm each chat message is a JSON object like {\"role\":\"user\",\"parts\":[...]}","Upgrade the emitting instrumentation (e.g. OpenTelemetry .NET GenAI exporters) so messages follow the documented GenAI content schema","Check for truncation of the recorded body (size limits when exporting) and re-export with larger limits","Wrap parsing in DeserializeWithErrorHandling so a malformed message is surfaced as a description instead of a raw JsonException"],"exampleFix":"// before\nvar message = JsonDocument.Parse(rawBody).RootElement[0]; // an array, not an object\n// after\nif (message.ValueKind == JsonValueKind.Object && message.TryGetProperty(\"role\", out _))\n{\n    var (role, parts, truncated) = GenAIMessageParsingHelper.ReadChatMessage(message);\n}","handlingStrategy":"try-catch","validationCode":"using var doc = JsonDocument.Parse(json);\nvar ok = doc.RootElement.ValueKind == JsonValueKind.Object &&\n         doc.RootElement.TryGetProperty(\"role\", out _);\nif (!ok) throw new FormatException(\"Chat message is not a JSON object with a role property.\");","typeGuard":"static bool IsChatMessageObject(JsonElement e) =>\n    e.ValueKind == JsonValueKind.Object && e.TryGetProperty(\"role\", out _);","tryCatchPattern":"try\n{\n    var (role, parts, truncated) = GenAIMessageParsingHelper.ReadChatMessage(element);\n}\ncatch (JsonException ex)\n{\n    logger.LogWarning(ex, \"Malformed GenAI chat message; rendering raw content instead.\");\n}","preventionTips":["Validate telemetry bodies with JsonDocument.Parse before incremental Utf8JsonReader parsing","Pin instrumentation versions so emitters and the dashboard agree on the message schema","Avoid hand-editing exported telemetry JSON"],"tags":["json","parsing","genai","telemetry"],"backgroundTag":"json-parse-error","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}