fix(gateway): increase WebSocket max payload to 5 MB for image uploads (#14486)

* fix(gateway): increase WebSocket max payload to 5 MB for image uploads

The 512 KB limit was too small for base64-encoded images — a 400 KB
image becomes ~532 KB after encoding, exceeding the limit and closing
the connection with code 1006.

Bump MAX_PAYLOAD_BYTES to 5 MB and MAX_BUFFERED_BYTES to 8 MB to
support standard image uploads via webchat.

Closes #14400

* fix: align gateway WS limits with 5MB image uploads (#14486) (thanks @0xRaini)

* docs: fix changelog conflict for #14486

---------

Co-authored-by: 0xRaini <0xRaini@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
0xRain
2026-02-13 00:48:49 +08:00
committed by GitHub
parent a2ddcdadeb
commit 626a1d0699
4 changed files with 6 additions and 5 deletions

View File

@@ -13,6 +13,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Gateway: raise WS payload/buffer limits so 5,000,000-byte image attachments work reliably. (#14486) Thanks @0xRaini.
- Cron: use requested `agentId` for isolated job auth resolution. (#13983) Thanks @0xRaini.
- Cron: prevent cron jobs from skipping execution when `nextRunAtMs` advances. (#14068) Thanks @WalterSumbon.
- Cron: pass `agentId` to `runHeartbeatOnce` for main-session jobs. (#14140) Thanks @ishikawa-pro.

View File

@@ -64,7 +64,7 @@ export async function parseMessageWithAttachments(
attachments: ChatAttachment[] | undefined,
opts?: { maxBytes?: number; log?: AttachmentLog },
): Promise<ParsedMessageWithImages> {
const maxBytes = opts?.maxBytes ?? 5_000_000; // 5 MB
const maxBytes = opts?.maxBytes ?? 5_000_000; // decoded bytes (5,000,000)
const log = opts?.log;
if (!attachments || attachments.length === 0) {
return { message, images: [] };

View File

@@ -1,5 +1,5 @@
export const MAX_PAYLOAD_BYTES = 512 * 1024; // cap incoming frame size
export const MAX_BUFFERED_BYTES = 1.5 * 1024 * 1024; // per-connection send buffer limit
export const MAX_PAYLOAD_BYTES = 8 * 1024 * 1024; // cap incoming frame size (~8 MiB; fits ~5,000,000 decoded bytes as base64 + JSON overhead)
export const MAX_BUFFERED_BYTES = 16 * 1024 * 1024; // per-connection send buffer limit (2x max payload)
const DEFAULT_MAX_CHAT_HISTORY_MESSAGES_BYTES = 6 * 1024 * 1024; // keep history responses comfortably under client WS limits
let maxChatHistoryMessagesBytes = DEFAULT_MAX_CHAT_HISTORY_MESSAGES_BYTES;

View File

@@ -44,7 +44,7 @@ describe("prepareSlackMessage sender prefix", () => {
ackReactionScope: "off",
mediaMaxBytes: 1000,
removeAckAfterReply: false,
logger: { info: vi.fn() },
logger: { info: vi.fn(), warn: vi.fn() },
markMessageSeen: () => false,
shouldDropMismatchedSlackEvent: () => false,
resolveSlackSystemEventSessionKey: () => "agent:main:slack:channel:c1",
@@ -123,7 +123,7 @@ describe("prepareSlackMessage sender prefix", () => {
ackReactionScope: "off",
mediaMaxBytes: 1000,
removeAckAfterReply: false,
logger: { info: vi.fn() },
logger: { info: vi.fn(), warn: vi.fn() },
markMessageSeen: () => false,
shouldDropMismatchedSlackEvent: () => false,
resolveSlackSystemEventSessionKey: () => "agent:main:slack:channel:c1",