Skip to content

Missing timeout: Polymarket WebSocket (user channel) — no connection timeout #243

@realfishsam

Description

@realfishsam

Location

core/src/exchanges/polymarket/websocket.ts:224

Code

private async connectUserChannel(creds: PolymarketUserChannelCreds): Promise<void> {
    const WebSocket = (await import('ws')).default;
    const url = 'wss://ws-subscriptions-clob.polymarket.com/ws/user';

    this.userWs = new WebSocket(url);

    this.userWs.on('open', () => {
        console.log('[polymarket-ws] user channel connected');
        this.sendUserSubscription(creds);
        // ...
    });

Risk

connectUserChannel creates a WebSocket without any connection timeout. The function itself is async but doesn't return a promise that settles on open — instead it fires-and-forgets. If the Polymarket user channel endpoint hangs, the authenticated user channel silently never establishes, and user-channel events (fills, position updates) are never received with no error surfaced.

Affected Methods

  • PolymarketWebSocket.connectUserChannel() — called for credentialed users
  • All user-channel event callbacks (fill notifications, position updates)

Suggested Fix

Wrap the connection in a promise with a timeout and reject on both error and timeout:

await new Promise<void>((resolve, reject) => {
    const timeout = setTimeout(() => {
        this.userWs?.terminate();
        reject(new Error('Polymarket user WS connection timeout'));
    }, 15_000);
    this.userWs!.on('open', () => { clearTimeout(timeout); resolve(); });
    this.userWs!.on('error', (err) => { clearTimeout(timeout); reject(err); });
});

Found by automated missing timeout audit

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions