{"id":"8d3c52cba12b13a5","repo":"socketio/socket.io","slug":"string-ev-is-a-reserved-event-name-8d3c52","errorCode":null,"errorMessage":"\"${String(ev)}\" is a reserved event name","messagePattern":"\"(.+?)\" is a reserved event name","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/socket.io-redis-streams-emitter/lib/index.ts","lineNumber":288,"sourceCode":"      this.publish,\n      this.rooms,\n      this.exceptRooms,\n      flags,\n    );\n  }\n\n  /**\n   * Emits to all clients.\n   *\n   * @return Always true\n   * @public\n   */\n  public emit<Ev extends EventNames<EmitEvents>>(\n    ev: Ev,\n    ...args: EventParams<EmitEvents, Ev>\n  ): true {\n    if (RESERVED_EVENTS.has(ev)) {\n      throw new Error(`\"${String(ev)}\" is a reserved event name`);\n    }\n\n    // set up packet object\n    const data = [ev, ...args];\n    const packet = {\n      type: 2, // EVENT\n      data: data,\n    };\n\n    const opts = {\n      rooms: [...this.rooms],\n      flags: this.flags,\n      except: [...this.exceptRooms],\n    };\n\n    this.publish({\n      type: MessageType.BROADCAST,\n      data: {","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/socketio/socket.io/blob/ae7fb46e08c5ed964b4a1ea8b1703e816511598e/packages/socket.io-redis-streams-emitter/lib/index.ts#L270-L306","documentation":"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.","triggerScenarios":"Calling emitter.emit('connect'), emitter.in(room).emit('disconnect'), or any emit() with a reserved event name on the socket.io-redis-streams-emitter.","commonSituations":"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.","solutions":["Rename the broadcast event to a non-reserved name like 'session:ended'.","Use a dedicated custom event for cross-cluster lifecycle notifications.","Guard dynamic event names against RESERVED_EVENTS before emitting."],"exampleFix":"// before\nemitter.emit('disconnect', userId);\n\n// after\nemitter.emit('session:ended', userId);","handlingStrategy":"validation","validationCode":"const RESERVED = new Set(['connect','connect_error','disconnect','disconnecting','newListener','removeListener']);\nfunction assertNotReserved(ev){ if(RESERVED.has(ev)) throw new Error(ev+' is reserved'); }","typeGuard":"function isEmittable(ev){ return !['connect','connect_error','disconnect','disconnecting','newListener','removeListener'].includes(ev); }","tryCatchPattern":null,"preventionTips":["Avoid emitting reserved lifecycle event names through the redis-streams emitter.","Pick a distinct custom event name for cluster notifications.","Guard dynamic event names before emit()."],"tags":["emitter","redis","reserved-events","broadcast"],"analyzedSha":"ae7fb46e08c5ed964b4a1ea8b1703e816511598e","analyzedAt":"2026-08-03T19:08:14.127Z","schemaVersion":2}