socketio/socket.io · error · Error

"${String(ev)}" is a reserved event name

Error message

"${String(ev)}" is a reserved event name

What it means

Thrown by the redis-streams-emitter's BroadcastOperator.emit() when the event name is in RESERVED_EVENTS (connect, connect_error, disconnect, disconnecting, newListener, removeListener). Same rationale as other emitters: these names are reserved by the protocol and broadcasting them would corrupt lifecycle handling on the receiving nodes.

Source

Thrown at packages/socket.io-redis-streams-emitter/lib/index.ts:288

      this.publish,
      this.rooms,
      this.exceptRooms,
      flags,
    );
  }

  /**
   * Emits to all clients.
   *
   * @return Always true
   * @public
   */
  public emit<Ev extends EventNames<EmitEvents>>(
    ev: Ev,
    ...args: EventParams<EmitEvents, Ev>
  ): true {
    if (RESERVED_EVENTS.has(ev)) {
      throw new Error(`"${String(ev)}" is a reserved event name`);
    }

    // set up packet object
    const data = [ev, ...args];
    const packet = {
      type: 2, // EVENT
      data: data,
    };

    const opts = {
      rooms: [...this.rooms],
      flags: this.flags,
      except: [...this.exceptRooms],
    };

    this.publish({
      type: MessageType.BROADCAST,
      data: {

View on GitHub (pinned to ae7fb46e08)

Solutions

  1. Rename the broadcast event to a non-reserved name like 'session:ended'.
  2. Use a dedicated custom event for cross-cluster lifecycle notifications.
  3. Guard dynamic event names against RESERVED_EVENTS before emitting.

Example fix

// before
emitter.emit('disconnect', userId);

// after
emitter.emit('session:ended', userId);
Defensive patterns

Strategy: validation

Validate before calling

const RESERVED = new Set(['connect','connect_error','disconnect','disconnecting','newListener','removeListener']);
function assertNotReserved(ev){ if(RESERVED.has(ev)) throw new Error(ev+' is reserved'); }

Type guard

function isEmittable(ev){ return !['connect','connect_error','disconnect','disconnecting','newListener','removeListener'].includes(ev); }

Prevention

When it happens

Trigger: Calling emitter.emit('connect'), emitter.in(room).emit('disconnect'), or any emit() with a reserved event name on the socket.io-redis-streams-emitter.

Common situations: Migrating from the old redis emitter API and reusing lifecycle event names; broadcasting disconnect/connect signals cluster-wide via emit() instead of a custom event.

Related errors


AI-assisted analysis of socketio/socket.io@ae7fb46e08 (2026-08-03). Data as JSON: /data/errors/8d3c52cba12b13a5.json. Report an issue: GitHub.