feat(realtime): expose granular server error types and payloads#144
feat(realtime): expose granular server error types and payloads#144VerioN1 wants to merge 9 commits into
Conversation
Previously, real-time server errors were generic. This change introduces `RealtimeWebSocketErrorType` and attaches it, along with the full server payload, to `ServerError` objects. New `REALTIME_` error codes are added to `DecartSDKError` to enable more specific error handling and debugging for different real-time issues like invalid API keys, insufficient credits, or moderation violations.
commit: |
| data?: RealtimeServerErrorData, | ||
| cause?: Error, | ||
| ): DecartSDKError { | ||
| const code = data?.errorType ? REALTIME_SERVER_ERROR_CODES[data.errorType] : ERROR_CODES.WEBRTC_SERVER_ERROR; |
There was a problem hiding this comment.
Unrecognized error type causes undefined error code
Medium Severity
If the server sends an error_type value not present in REALTIME_SERVER_ERROR_CODES (e.g., a newly added server error type before the SDK is updated), REALTIME_SERVER_ERROR_CODES[data.errorType] evaluates to undefined at runtime. This produces a DecartSDKError with code: undefined, violating the code: string type contract and potentially breaking downstream error-handling logic. The incoming message is only type-asserted (as IncomingRealtimeMessage) without validation, so unrecognized values can flow through unchecked. A fallback to WEBRTC_SERVER_ERROR when the lookup misses would prevent this.
Reviewed by Cursor Bugbot for commit aca3c82. Configure here.
| for (const [groupKey, fields] of statsAggregates) { | ||
| const group = {}; | ||
| for (const [field, { sum, count }] of fields) { | ||
| group[field] = sum; |
There was a problem hiding this comment.
Stats summary outputs sums instead of averages
Medium Severity
buildStatsSummary assigns sum directly to each field but the UI button says "Print Avg Stats" and the console log says "Stats averages." The count is destructured but never used for division. The aggregateStatObject function carefully accumulates both sum and count specifically to enable averaging, but the final computation group[field] = sum omits the / count division, producing misleading raw totals instead of averages.
Reviewed by Cursor Bugbot for commit 1ea50a6. Configure here.
| } | ||
| } | ||
| return { sender: [], receiver }; | ||
| }, |
There was a problem hiding this comment.
Receiver stats logic duplicated across two files
Low Severity
The receiver stats gathering logic (iterating remoteParticipants, filtering by identity prefix, checking instanceof RemoteVideoTrack, calling getReceiverStats()) is identically duplicated between MediaChannel.getVideoStats() and the subscribe client's inline getVideoStats. A bug fix in one location would need to be replicated in the other. This could be extracted into a shared utility.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 1ea50a6. Configure here.
1ea50a6 to
42ea6a2
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
There are 5 total unresolved issues (including 3 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 48a31d1. Configure here.
| pauseCount: inbound?.pauseCount, | ||
| totalPausesDuration: inbound?.totalPausesDuration, | ||
| keyFramesDecoded: inbound?.keyFramesDecoded, | ||
| codecMimeType: mime ? mime.slice(mime.indexOf("/") + 1).toUpperCase() : undefined, |
There was a problem hiding this comment.
Subscriber stats missing framesPerSecond field unlike publisher
Medium Severity
The enrichReceiverFromReport function in subscribe-client.ts omits framesPerSecond from both its RawInbound type and the merged result, while the equivalent mergeReceiver in media-channel.ts correctly includes it. This means getVideoStats() on the subscribe client will never populate framesPerSecond in receiver stats, creating an inconsistency with the publisher client's stats API.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 48a31d1. Configure here.


Previously, real-time server errors were generic. This change introduces
RealtimeWebSocketErrorTypeand attaches it, along with the full serverpayload, to
ServerErrorobjects. NewREALTIME_error codes areadded to
DecartSDKErrorto enable more specific error handling anddebugging for different real-time issues like invalid API keys,
insufficient credits, or moderation violations.
Note
High Risk
Large SDK surface changes (video-only publish/subscribe, new connect options) plus an enormous demo page refactor; integrators relying on mic audio or generic server errors need to verify behavior.
Overview
This PR extends the realtime SDK and turns the SDK test page into a LiveKit publish benchmarking lab.
SDK: Signaling
errormessages now carryerror_typeand the full payload onServerError, mapped to newREALTIME_*DecartSDKErrorcodes (with tests). Connect/subscribe accept optionalpublishOptions,roomOptions, andremoteVideoElement;getVideoStats()exposes enriched sender/receiver WebRTC stats (QP, freezes, codecs, etc.). Publishing is video-only (audio tracks dropped from mirror/publish paths); remote inference tracks attach to a provided element when set.Demo (
index.html+ workers): Adds a benchmark dashboard (Chart.js charts, timed runs, CSV/PNG export viacompute-worker.js), sequential profile chains (H.264/VP9/AV1 presets) with optional continuous chain recording, file/canvas camera pipelines with QR frame counters for end-to-end latency (barcode-worker.js), stats polling, prompt cycling, and related UI controls.Reviewed by Cursor Bugbot for commit 66a0fea. Bugbot is set up for automated code reviews on this repo. Configure here.