{"record":{"id":"c51a2e452fb5b1e3","repo":"microsoft/aspire","slug":"tracked-browser-protocol-frame-ended-unexpectedly","errorCode":null,"errorMessage":"Tracked browser protocol frame ended unexpectedly.","messagePattern":"Tracked browser protocol frame ended unexpectedly\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Browsers/BrowserLogsCdpProtocol.cs","lineNumber":89,"sourceCode":"        string? method = null;\n        string? sessionId = null;\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 InvalidOperationException(\"Tracked browser protocol frame was malformed.\");\n            }\n\n            var propertyName = reader.GetString();\n            if (!reader.Read())\n            {\n                throw new InvalidOperationException(\"Tracked browser protocol frame ended unexpectedly.\");\n            }\n\n            switch (propertyName)\n            {\n                case \"id\":\n                    if (!reader.TryGetInt64(out var parsedId))\n                    {\n                        throw new InvalidOperationException(\"Tracked browser protocol response id was not an integer.\");\n                    }\n\n                    id = parsedId;\n                    break;\n                case \"method\":\n                    method = reader.TokenType == JsonTokenType.String\n                        ? reader.GetString()\n                        : throw new InvalidOperationException(\"Tracked browser protocol event method was not a string.\");\n                    break;\n                case \"sessionId\":","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Browsers/BrowserLogsCdpProtocol.cs#L71-L107","documentation":"While parsing a CDP frame header, the parser reads the value for each property name. If the JSON stream ends right after a property name (no value token follows), the frame is truncated and this InvalidOperationException is thrown. It indicates the tracked browser's frame ended mid-object.","triggerScenarios":"ParseMessageHeader encounters a property name token but Utf8JsonReader.Read() returns false - i.e. the payload ends immediately after a key like {\"id\": or a final dangling key, typically a truncated or partial frame.","commonSituations":"Socket/stream read returned a partial frame, buffer boundary split a JSON object mid-key, the browser process crashed or was killed mid-write, or network disconnect during DevTools message delivery.","solutions":["Verify frame-length framing so only complete frames are handed to the parser","Log the raw payload via DescribeFrame to confirm truncation","Check browser process health - a crash can truncate the last frame","Buffer and reassemble partial reads before parsing","Catch the exception and re-establish the browser connection"],"exampleFix":"// before\nvar header = BrowserLogsCdpProtocol.ParseMessageHeader(partialBuffer);\n// after\nif (!frameReader.TryReadCompleteFrame(out var frame))\n{\n    pendingBuffer = frame; // wait for more data\n    return;\n}\nvar header = BrowserLogsCdpProtocol.ParseMessageHeader(frame);","handlingStrategy":"validation","validationCode":"// Only parse frames known to be complete per the framing protocol\nif (!TryReadCompleteFrame(ref buffer, out var frame))\n{\n    return; // wait for remainder\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Implement full frame-length reassembly before parsing","Handle partial socket reads by buffering","Monitor browser process liveness to detect crash-truncation","Log truncated frames with DescribeFrame"],"tags":["cdp","browser","truncated-frame","json"],"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"}