diff --git a/docs/pages/api-reference/liveblocks-client.mdx b/docs/pages/api-reference/liveblocks-client.mdx index 8ba9c416407..d7fa7395038 100644 --- a/docs/pages/api-reference/liveblocks-client.mdx +++ b/docs/pages/api-reference/liveblocks-client.mdx @@ -195,7 +195,7 @@ const client = createClient({ How to handle WebSocket messages that are larger than the maximum message size. Can be set to one of these values: - - `"default"` Don’t send anything, but log the error to the console. + - `"default"` Don’t send anything, but log the error to the console and notify useErrorListener. - `"split"` Break the message up into chunks each of which is smaller than the maximum message size. Beware that using `"split"` will sacrifice atomicity of changes! Depending on your use case, this may or may not be problematic. - `"experimental-fallback-to-http"` Try sending the update over HTTP instead of WebSockets (experimental). diff --git a/docs/pages/api-reference/liveblocks-react.mdx b/docs/pages/api-reference/liveblocks-react.mdx index 5fa5a2ec4f7..d52f54e6be5 100644 --- a/docs/pages/api-reference/liveblocks-react.mdx +++ b/docs/pages/api-reference/liveblocks-react.mdx @@ -396,7 +396,7 @@ function App() { How to handle WebSocket messages that are larger than the maximum message size. Can be set to one of these values: - - `"default"` Don’t send anything, but log the error to the console. + - `"default"` Don’t send anything, but log the error to the console and notify useErrorListener. - `"split"` Break the message up into chunks each of which is smaller than the maximum message size. Beware that using `"split"` will sacrifice atomicity of changes! Depending on your use case, this may or may not be problematic. - `"experimental-fallback-to-http"` Try sending the update over HTTP instead of WebSockets (experimental). diff --git a/packages/liveblocks-core/src/room.ts b/packages/liveblocks-core/src/room.ts index 852f1c47972..24f4d51fb8e 100644 --- a/packages/liveblocks-core/src/room.ts +++ b/packages/liveblocks-core/src/room.ts @@ -1733,8 +1733,16 @@ export function createRoom< // If message is too big for WebSockets, we need to follow a strategy switch (strategy) { case "default": { - console.error("Message is too large for websockets, not sending. Configure largeMessageStrategy option to deal with this."); // prettier-ignore - // Don't send the message + const type = "LARGE_MESSAGE_ERROR"; + const err = new LiveblocksError("Message is too large for websockets", { + type, + }); + const didNotify = config.errorEventSource.notify(err); + if (!didNotify) { + console.error( + "Message is too large for websockets. Configure largeMessageStrategy option or useErrorListener to handle this." + ); + } return; } diff --git a/packages/liveblocks-core/src/types/LiveblocksError.ts b/packages/liveblocks-core/src/types/LiveblocksError.ts index 0f174655cae..9cf4f30cddb 100644 --- a/packages/liveblocks-core/src/types/LiveblocksError.ts +++ b/packages/liveblocks-core/src/types/LiveblocksError.ts @@ -16,6 +16,10 @@ type RoomConnectionErrorContext = { roomId: string; }; +type LargeMessageErrorContext = { + type: "LARGE_MESSAGE_ERROR"; +}; + // All possible errors originating from using Comments or Notifications type CommentsOrNotificationsErrorContext = | { @@ -92,6 +96,7 @@ export type LiveblocksErrorContext = Relax< | RoomConnectionErrorContext // from Presence, Storage, or Yjs | CommentsOrNotificationsErrorContext // from Comments or Notifications or UserNotificationSettings | AiConnectionErrorContext // from AI + | LargeMessageErrorContext // whena message is too large >; export class LiveblocksError extends Error { @@ -166,6 +171,7 @@ function defaultMessageFromContext(context: LiveblocksErrorContext): string { case "DELETE_ALL_INBOX_NOTIFICATIONS_ERROR": return "Could not delete all inbox notifications"; case "UPDATE_ROOM_SUBSCRIPTION_SETTINGS_ERROR": return "Could not update room subscription settings"; case "UPDATE_NOTIFICATION_SETTINGS_ERROR": return "Could not update notification settings"; + case "LARGE_MESSAGE_ERROR": return "Could not send large message"; default: return assertNever(context, "Unhandled case"); diff --git a/packages/liveblocks-react/test-d/augmentation.test-d.tsx b/packages/liveblocks-react/test-d/augmentation.test-d.tsx index b2f258e5b10..c3fc09bf984 100644 --- a/packages/liveblocks-react/test-d/augmentation.test-d.tsx +++ b/packages/liveblocks-react/test-d/augmentation.test-d.tsx @@ -27,8 +27,8 @@ declare global { }; RoomEvent: - | { type: "emoji"; emoji: string } - | { type: "beep"; times?: number }; + | { type: "emoji"; emoji: string } + | { type: "beep"; times?: number }; ThreadMetadata: { color: "red" | "blue"; @@ -330,6 +330,7 @@ declare global { | "DELETE_ALL_INBOX_NOTIFICATIONS_ERROR" | "UPDATE_ROOM_SUBSCRIPTION_SETTINGS_ERROR" | "UPDATE_NOTIFICATION_SETTINGS_ERROR" + | "LARGE_MESSAGE_ERROR" >(err.context.type); if (err.context.type === "ROOM_CONNECTION_ERROR") { expectAssignable(err.context.code); @@ -373,6 +374,7 @@ declare global { | "DELETE_ALL_INBOX_NOTIFICATIONS_ERROR" | "UPDATE_ROOM_SUBSCRIPTION_SETTINGS_ERROR" | "UPDATE_NOTIFICATION_SETTINGS_ERROR" + | "LARGE_MESSAGE_ERROR" >(err.context.type); if (err.context.type === "ROOM_CONNECTION_ERROR") { expectAssignable(err.context.code); diff --git a/packages/liveblocks-react/test-d/factories.test-d.tsx b/packages/liveblocks-react/test-d/factories.test-d.tsx index 962f0df2bd0..1e14dce5cb3 100644 --- a/packages/liveblocks-react/test-d/factories.test-d.tsx +++ b/packages/liveblocks-react/test-d/factories.test-d.tsx @@ -378,6 +378,7 @@ ctx.useOthersListener(({ user, type }) => { | "DELETE_ALL_INBOX_NOTIFICATIONS_ERROR" | "UPDATE_ROOM_SUBSCRIPTION_SETTINGS_ERROR" | "UPDATE_NOTIFICATION_SETTINGS_ERROR" + | "LARGE_MESSAGE_ERROR" >(err.context.type); if (err.context.type === "ROOM_CONNECTION_ERROR") { expectAssignable(err.context.code); @@ -418,6 +419,7 @@ ctx.useOthersListener(({ user, type }) => { | "DELETE_ALL_INBOX_NOTIFICATIONS_ERROR" | "UPDATE_ROOM_SUBSCRIPTION_SETTINGS_ERROR" | "UPDATE_NOTIFICATION_SETTINGS_ERROR" + | "LARGE_MESSAGE_ERROR" >(err.context.type); if (err.context.type === "ROOM_CONNECTION_ERROR") { expectAssignable(err.context.code); @@ -458,6 +460,7 @@ ctx.useOthersListener(({ user, type }) => { | "DELETE_ALL_INBOX_NOTIFICATIONS_ERROR" | "UPDATE_ROOM_SUBSCRIPTION_SETTINGS_ERROR" | "UPDATE_NOTIFICATION_SETTINGS_ERROR" + | "LARGE_MESSAGE_ERROR" >(err.context.type); if (err.context.type === "ROOM_CONNECTION_ERROR") { expectAssignable(err.context.code); diff --git a/packages/liveblocks-react/test-d/no-augmentation.test-d.tsx b/packages/liveblocks-react/test-d/no-augmentation.test-d.tsx index 7da31848f82..f0b7f3e33da 100644 --- a/packages/liveblocks-react/test-d/no-augmentation.test-d.tsx +++ b/packages/liveblocks-react/test-d/no-augmentation.test-d.tsx @@ -232,6 +232,7 @@ import { expectAssignable, expectError, expectType } from "tsd"; | "DELETE_ALL_INBOX_NOTIFICATIONS_ERROR" | "UPDATE_ROOM_SUBSCRIPTION_SETTINGS_ERROR" | "UPDATE_NOTIFICATION_SETTINGS_ERROR" + | "LARGE_MESSAGE_ERROR" >(err.context.type); if (err.context.type === "ROOM_CONNECTION_ERROR") { expectAssignable(err.context.code); @@ -275,6 +276,7 @@ import { expectAssignable, expectError, expectType } from "tsd"; | "DELETE_ALL_INBOX_NOTIFICATIONS_ERROR" | "UPDATE_ROOM_SUBSCRIPTION_SETTINGS_ERROR" | "UPDATE_NOTIFICATION_SETTINGS_ERROR" + | "LARGE_MESSAGE_ERROR" >(err.context.type); if (err.context.type === "ROOM_CONNECTION_ERROR") { expectAssignable(err.context.code);